Freigeben über


Verwenden von SQL-Cacheabhängigkeiten (C#)

von Scott Mitchell

PDF herunterladen

Die einfachste Zwischenspeicherungsstrategie besteht darin, zuzulassen, dass zwischengespeicherte Daten nach einem bestimmten Zeitraum ablaufen. Dieser einfache Ansatz bedeutet jedoch, dass die zwischengespeicherten Daten keine Zuordnung zu ihrer zugrunde liegenden Datenquelle beibehalten, was zu veralteten Daten führt, die zu lange aufbewahrt werden, oder aktuelle Daten, die zu früh abgelaufen sind. Ein besserer Ansatz besteht darin, die SqlCacheDependency-Klasse zu verwenden, sodass Die Daten zwischengespeichert bleiben, bis die zugrunde liegenden Daten in der SQL-Datenbank geändert wurden. In diesem Tutorial erfahren Sie, wie.

Einführung

Die in den Tutorials "Zwischenspeichern von Daten mit ObjectDataSource" und "Daten zwischenspeichern" in den Tutorials "Architektur" untersuchten Zwischenspeicherungstechniken verwendeten einen zeitbasierten Ablauf, um die Daten nach einem bestimmten Zeitraum aus dem Cache zu entfernen. Dieser Ansatz ist der einfachste Weg, um die Leistungsgewinne des Zwischenspeicherns mit der Veraltetkeit von Daten auszugleichen. Durch die Auswahl eines Zeitablaufs von x Sekunden, gibt ein Seitenentwickler zu, die Leistungsvorteile des Zwischenspeicherns nur für x Sekunden zu nutzen, kann aber einfach sein, dass seine Daten nie länger als maximal x Sekunden veraltet sind. Für statische Daten kann x natürlich auf die Lebensdauer der Webanwendung erweitert werden, wie im Tutorial Zwischenspeichern von Daten beim Anwendungsstart untersucht wurde.

Beim Zwischenspeichern von Datenbankdaten wird häufig ein zeitbasierter Ablauf aus Gründen der Benutzerfreundlichkeit gewählt, ist aber häufig eine unzureichende Lösung. Im Idealfall bleiben die Datenbankdaten zwischengespeichert, bis die zugrunde liegenden Daten in der Datenbank geändert wurden. nur dann würde der Cache entfernt. Dieser Ansatz maximiert die Leistungsvorteile des Zwischenspeicherns und minimiert die Dauer veralteter Daten. Um diese Vorteile nutzen zu können, muss jedoch ein System vorhanden sein, das weiß, wann die zugrunde liegenden Datenbankdaten geändert wurden, und die entsprechenden Elemente aus dem Cache entfernt. Vor ASP.NET 2.0 waren Seitenentwickler für die Implementierung dieses Systems verantwortlich.

ASP.NET 2.0 stellt eine SqlCacheDependency Klasse und die erforderliche Infrastruktur bereit, um zu bestimmen, wann eine Änderung in der Datenbank erfolgt ist, sodass die entsprechenden zwischengespeicherten Elemente entfernt werden können. Es gibt zwei Techniken, um zu bestimmen, wann sich die zugrunde liegenden Daten geändert haben: Benachrichtigungen und Abfragen. Nachdem wir die Unterschiede zwischen Benachrichtigungen und Abfragen erläutert haben, erstellen wir die erforderliche Infrastruktur, um die Abfrage zu unterstützen, und untersuchen dann, wie die SqlCacheDependency Klasse in deklarativen und programmgesteuerten Szenarien verwendet werden kann.

Grundlegendes zu Benachrichtigungen und Abfragen

Es gibt zwei Techniken, die verwendet werden können, um zu bestimmen, wann die Daten in einer Datenbank geändert wurden: Benachrichtigung und Abfrage. Mit der Benachrichtigung benachrichtigt die Datenbank automatisch die ASP.NET Runtime, wenn die Ergebnisse einer bestimmten Abfrage seit der letzten Ausführung der Abfrage geändert wurden, und an diesem Punkt die zwischengespeicherten Elemente, die der Abfrage zugeordnet sind, entfernt werden. Beim Abfragen verwaltet der Datenbankserver Informationen darüber, wann bestimmte Tabellen zuletzt aktualisiert wurden. Die ASP.NET Runtime fragt in regelmäßigen Abständen die Datenbank ab, um zu überprüfen, welche Tabellen sich seit der Eingabe in den Cache geändert haben. Für Tabellen, deren Daten geändert wurden, wurden die zugeordneten Cacheelemente entfernt.

Die Benachrichtigungsoption erfordert eine geringere Einrichtung als die Abfrage und ist präziser, da änderungen auf Abfrageebene und nicht auf Tabellenebene nachverfolgt werden. Leider sind Benachrichtigungen nur in den Vollversionen von Microsoft SQL Server 2005 (d. h. den Nicht-Express-Editionen) verfügbar. Die Abfrageoption kann jedoch für alle Versionen von Microsoft SQL Server von 7.0 bis 2005 verwendet werden. Da diese Tutorials die Express-Edition von SQL Server 2005 verwenden, konzentrieren wir uns auf das Einrichten und Verwenden der Abfrageoption. Weitere Ressourcen zu SQL Server Benachrichtigungsfunktionen von 2005 finden Sie im Abschnitt Weitere Informationen am Ende dieses Tutorials.

Bei der Abfrage muss die Datenbank so konfiguriert werden, dass sie eine Tabelle mit dem Namen enthält AspNet_SqlCacheTablesForChangeNotification , die drei Spalten enthält: tableName, notificationCreatedund changeId. Diese Tabelle enthält eine Zeile für jede Tabelle, die Daten enthält, die möglicherweise in einer SQL-Cacheabhängigkeit in der Webanwendung verwendet werden müssen. Die tableName Spalte gibt den Namen der Tabelle an, während notificationCreated das Datum und die Uhrzeit des Hinzufügens der Zeile zur Tabelle angegeben werden. Die changeId Spalte ist vom Typ int und hat den Anfangswert 0. Sein Wert wird mit jeder Änderung der Tabelle erhöht.

Zusätzlich zur AspNet_SqlCacheTablesForChangeNotification Tabelle muss die Datenbank auch Trigger für jede der Tabellen enthalten, die möglicherweise in einer SQL-Cacheabhängigkeit angezeigt werden. Diese Trigger werden immer dann ausgeführt, wenn eine Zeile eingefügt, aktualisiert oder gelöscht wird, und erhöhen sie den Wert der Tabelle changeId in AspNet_SqlCacheTablesForChangeNotification.

Die ASP.NET Runtime verfolgt den aktuellen changeId für eine Tabelle nach, wenn Daten mithilfe eines SqlCacheDependency -Objekts zwischengespeichert werden. Die Datenbank wird in regelmäßigen Abständen überprüft, und alle SqlCacheDependency Objekte, deren changeId Wert sich vom Wert in der Datenbank unterscheidet, werden entfernt, da ein unterschiedlicher changeId Wert angibt, dass seit dem Zwischenspeichern der Daten eine Änderung an der Tabelle aufgetreten ist.

Schritt 1: Erkunden des Befehlszeilenprogrammsaspnet_regsql.exe

Beim Abfrageansatz muss die Datenbank so eingerichtet werden, dass sie die oben beschriebene Infrastruktur enthält: eine vordefinierte Tabelle (AspNet_SqlCacheTablesForChangeNotification), eine Handvoll gespeicherter Prozeduren und Trigger für jede der Tabellen, die in SQL-Cacheabhängigkeiten in der Webanwendung verwendet werden können. Diese Tabellen, gespeicherten Prozeduren und Trigger können über das Befehlszeilenprogramm aspnet_regsql.exeerstellt werden, das sich im $WINDOWS$\Microsoft.NET\Framework\version Ordner befindet. Um die Tabelle und die AspNet_SqlCacheTablesForChangeNotification zugeordneten gespeicherten Prozeduren zu erstellen, führen Sie über die Befehlszeile Folgendes aus:

/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed

Hinweis

Zum Ausführen dieser Befehle muss sich die angegebene Datenbankanmeldung in den db_securityadmin Rollen und db_ddladmin befinden.

Wenn Sie beispielsweise die Infrastruktur für die Abfrage einer Microsoft SQL Server-Datenbank namens auf einem Datenbankserver namens pubsScottsServer mithilfe der Windows-Authentifizierung hinzufügen möchten, navigieren Sie zum entsprechenden Verzeichnis, und geben Sie in der Befehlszeile Folgendes ein:

aspnet_regsql.exe -S ScottsServer -E -d pubs -ed

Nachdem die Infrastruktur auf Datenbankebene hinzugefügt wurde, müssen wir die Trigger zu den Tabellen hinzufügen, die in SQL-Cacheabhängigkeiten verwendet werden. Verwenden Sie das aspnet_regsql.exe Befehlszeilenprogramm erneut, aber geben Sie den Tabellennamen mithilfe des -t Schalters an, und verwenden Sie -etanstelle des Schalters -ed wie folgt:

/* For SQL Server authentication... */
aspnet_regsql.exe -S <i>server</i>
-U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
/* For Windows Authentication... */
aspnet_regsql.exe -S <i>server</i>
-E -d <i>database</i> -t <i>tableName</i> -et

Um die Trigger den Tabellen und titles in der authorspubs Datenbank auf ScottsServerhinzuzufügen, verwenden Sie Folgendes:

aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et

Fügen Sie für dieses Tutorial die Trigger den ProductsTabellen , Categoriesund Suppliers hinzu. Wir sehen uns die bestimmte Befehlszeilensyntax in Schritt 3 an.

Schritt 2: Verweisen auf eine Microsoft SQL Server 2005 Express Edition-Datenbank inApp_Data

Das aspnet_regsql.exe Befehlszeilenprogramm erfordert den Datenbank- und Servernamen, um die erforderliche Abrufinfrastruktur hinzuzufügen. Aber wie lautet der Datenbank- und Servername für eine Microsoft SQL Server 2005 Express-Datenbank, die App_Data sich im Ordner befindet? Anstatt die Datenbank- und Servernamen ermitteln zu müssen, habe ich festgestellt, dass der einfachste Ansatz darin besteht, die Datenbank an die localhost\SQLExpress Datenbank anzufügen instance und die Daten mithilfe von SQL Server Management Studio umzubenennen. Wenn Sie eine der Vollversionen von SQL Server 2005 auf Ihrem Computer installiert haben, haben Sie wahrscheinlich bereits SQL Server Management Studio auf Ihrem Computer installiert. Wenn Sie nur über die Express-Edition verfügen, können Sie die kostenlose Microsoft SQL Server Management Studio Express Edition herunterladen.

Schließen Sie zunächst Visual Studio. Öffnen Sie als Nächstes SQL Server Management Studio, und stellen Sie eine Verbindung mit dem Server mithilfe der localhost\SQLExpress Windows-Authentifizierung her.

Anfügen an localhost\SQLExpress Server

Abbildung 1: Anfügen an den localhost\SQLExpress Server

Nach dem Herstellen einer Verbindung mit dem Server zeigt Management Studio den Server an und verfügt über Unterordner für die Datenbanken, die Sicherheit usw. Klicken Sie mit der rechten Maustaste auf den Ordner Datenbanken, und wählen Sie die Option Anfügen aus. Dadurch wird das Dialogfeld Datenbanken anfügen geöffnet (siehe Abbildung 2). Klicken Sie auf die Schaltfläche Hinzufügen, und wählen Sie den NORTHWND.MDF Datenbankordner im Ordner Ihrer Webanwendung aus App_Data .

Fügen Sie den NORTHWND an. MDF-Datenbank aus dem ordner App_Data

Abbildung 2: Anfügen der NORTHWND.MDF Datenbank aus dem App_Data Ordner (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Dadurch wird die Datenbank dem Ordner Datenbanken hinzugefügt. Der Datenbankname kann der vollständige Pfad zur Datenbankdatei oder der vollständige Pfad sein, dem eine GUID vorangestellt ist. Um zu vermeiden, dass Sie diesen langen Datenbanknamen eingeben müssen, wenn Sie das Befehlszeilentool aspnet_regsql.exe verwenden, benennen Sie die Datenbank in einen benutzerfreundlicheren Namen um, indem Sie mit der rechten Maustaste auf die gerade angefügte Datenbank klicken und Umbenennen auswählen. Ich habe meine Datenbank in DataTutorials umbenannt.

Umbenennen der angefügten Datenbank in einen Human-Friendly Namen

Abbildung 3: Umbenennen der angefügten Datenbank in einen Human-Friendly Namen

Schritt 3: Hinzufügen der Abfrageinfrastruktur zur Northwind-Datenbank

Nachdem wir die Datenbank aus dem NORTHWND.MDFApp_Data Ordner angefügt haben, können wir die Abfrageinfrastruktur hinzufügen. Wenn Sie die Datenbank in DataTutorials umbenannt haben, führen Sie die folgenden vier Befehle aus:

aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -ed
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Products -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Categories -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Suppliers -et

Nachdem Sie diese vier Befehle ausgeführt haben, klicken Sie mit der rechten Maustaste in Management Studio auf den Datenbanknamen, wechseln Sie zum Untermenü Aufgaben, und wählen Sie Trennen aus. Schließen Sie dann Management Studio, und öffnen Sie Visual Studio erneut.

Nachdem Visual Studio erneut geöffnet wurde, führen Sie einen Drilldown in die Datenbank über den Server Explorer. Notieren Sie sich die neue Tabelle (AspNet_SqlCacheTablesForChangeNotification), die neuen gespeicherten Prozeduren und die Trigger für die ProductsTabellen , Categoriesund Suppliers .

Die Datenbank enthält jetzt die erforderliche Abfrageinfrastruktur.

Abbildung 4: Die Datenbank enthält jetzt die erforderliche Abfrageinfrastruktur

Schritt 4: Konfigurieren des Abrufdiensts

Nach dem Erstellen der benötigten Tabellen, Trigger und gespeicherten Prozeduren in der Datenbank besteht der letzte Schritt darin, den Abrufdienst zu konfigurieren. Hierzu werden Web.config die zu verwendenden Datenbanken und die Abrufhäufigkeit in Millisekunden angegeben. Das folgende Markup fragt die Northwind-Datenbank einmal pro Sekunde ab.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="NORTHWNDConnectionString" connectionString=
          "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;
           Integrated Security=True;User Instance=True" 
           providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      ...
      <!-- Configure the polling service used for SQL cache dependencies -->
      <caching>
         <sqlCacheDependency enabled="true" pollTime="1000" >
            <databases>
               <add name="NorthwindDB" 
                    connectionStringName="NORTHWNDConnectionString" />
            </databases>
         </sqlCacheDependency>
      </caching>
   </system.web>
</configuration>

Der name Wert im <add> Element ( NorthwindDB ) ordnet einer bestimmten Datenbank einen lesbaren Namen zu. Bei der Arbeit mit SQL-Cacheabhängigkeiten müssen wir auf den hier definierten Datenbanknamen und die Tabelle verweisen, auf der die zwischengespeicherten Daten basieren. In Schritt 6 erfahren Sie, wie Sie die SqlCacheDependency -Klasse verwenden, um SQL-Cacheabhängigkeiten programmgesteuert mit zwischengespeicherten Daten zuzuordnen.

Sobald eine SQL-Cacheabhängigkeit eingerichtet wurde, stellt das Abfragesystem alle pollTime Millisekunden eine Verbindung mit den in den <databases> Elementen definierten Datenbanken her und führt die AspNet_SqlCachePollingStoredProcedure gespeicherte Prozedur aus. Diese gespeicherte Prozedur , die in Schritt 3 mithilfe des aspnet_regsql.exe Befehlszeilentools wieder hinzugefügt wurde, gibt die tableName Werte und changeId für jeden Datensatz in AspNet_SqlCacheTablesForChangeNotificationzurück. Veraltete SQL-Cacheabhängigkeiten werden aus dem Cache entfernt.

Die pollTime Einstellung führt einen Kompromiss zwischen Leistung und Datenalter ein. Ein kleiner pollTime Wert erhöht die Anzahl der Anforderungen an die Datenbank, räumt jedoch veraltete Daten schneller aus dem Cache. Ein größerer pollTime Wert reduziert die Anzahl von Datenbankanforderungen, erhöht jedoch die Verzögerung zwischen dem Ändern der Back-End-Daten und dem Entfernen der zugehörigen Cacheelemente. Glücklicherweise führt die Datenbankanforderung eine einfache gespeicherte Prozedur aus, die nur einige Zeilen aus einer einfachen, einfachen Tabelle zurückgibt. Experimentieren Sie jedoch mit verschiedenen pollTime Werten, um ein ideales Gleichgewicht zwischen Datenbankzugriff und Datenveraltung für Ihre Anwendung zu finden. Der kleinste pollTime zulässige Wert ist 500.

Hinweis

Im obigen Beispiel wird ein einzelner pollTime Wert im <sqlCacheDependency> -Element bereitgestellt, sie können jedoch optional den pollTime Wert im <add> -Element angeben. Dies ist nützlich, wenn Sie mehrere Datenbanken angegeben haben und die Abrufhäufigkeit pro Datenbank anpassen möchten.

Schritt 5: Deklaratives Arbeiten mit SQL-Cacheabhängigkeiten

In den Schritten 1 bis 4 haben wir uns mit dem Einrichten der erforderlichen Datenbankinfrastruktur und dem Konfigurieren des Abrufsystems befasst. Wenn diese Infrastruktur eingerichtet ist, können wir dem Datencache nun Elemente mit einer zugeordneten SQL-Cacheabhängigkeit hinzufügen, indem wir entweder programmgesteuerte oder deklarative Techniken verwenden. In diesem Schritt wird untersucht, wie Sie deklarativ mit SQL-Cacheabhängigkeiten arbeiten. In Schritt 6 sehen wir uns den programmgesteuerten Ansatz an.

Im Tutorial Zum Zwischenspeichern von Daten mit ObjectDataSource wurden die Funktionen des deklarativen Zwischenspeicherns von ObjectDataSource untersucht. Indem Sie einfach die EnableCaching -Eigenschaft auf true und die CacheDuration -Eigenschaft auf ein bestimmtes Zeitintervall festlegen, speichert ObjectDataSource automatisch die Daten zwischen, die von ihrem zugrunde liegenden Objekt für das angegebene Intervall zurückgegeben werden. Die ObjectDataSource kann auch eine oder mehrere SQL-Cacheabhängigkeiten verwenden.

Um die verwendung von SQL-Cacheabhängigkeiten deklarativ zu veranschaulichen, öffnen Sie die SqlCacheDependencies.aspx Seite im Caching Ordner, und ziehen Sie ein GridView-Objekt aus der Toolbox auf die Designer. Legen Sie die GridViews ID auf ProductsDeclarative fest, und wählen Sie aus ihrem Smarttag aus, um sie an eine neue ObjectDataSource namens ProductsDataSourceDeclarativezu binden.

Erstellen einer neuen ObjectDataSource mit dem Namen ProductsDataSourceDeclarative

Abbildung 5: Erstellen einer neuen ObjectDataSource namens ProductsDataSourceDeclarative (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Konfigurieren Sie objectDataSource für die Verwendung der ProductsBLL -Klasse, und legen Sie die Dropdownliste auf der Registerkarte SELECT auf fest GetProducts(). Wählen Sie auf der Registerkarte UPDATE die UpdateProduct Überladung mit den drei Eingabeparametern productName, unitPriceund productIDaus. Legen Sie die Dropdownlisten auf den Registerkarten INSERT und DELETE auf (Keine) fest.

Verwenden der UpdateProduct-Überladung mit drei Eingabeparametern

Abbildung 6: Verwenden der UpdateProduct-Überladung mit drei Eingabeparametern (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Legen Sie die Drop-Down Liste für die Registerkarten INSERT und DELETE auf (Keine) fest.

Abbildung 7: Festlegen der Drop-Down Liste auf (Keine) für die Registerkarten INSERT und DELETE (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Nach Abschluss des Assistenten zum Konfigurieren von Datenquellen erstellt Visual Studio boundFields und CheckBoxFields in GridView für jedes der Datenfelder. Entfernen Sie alle Felder außer ProductName, CategoryNameund UnitPrice, und formatieren Sie diese Felder nach Bedarf. Aktivieren Sie im Smarttag von GridView die Kontrollkästchen Paging aktivieren, Sortierung aktivieren und Bearbeitung aktivieren. Visual Studio legt die ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf fest original_{0}. Damit das Bearbeitungsfeature von GridView ordnungsgemäß funktioniert, entfernen Sie diese Eigenschaft entweder vollständig aus der deklarativen Syntax, oder legen Sie sie wieder auf ihren Standardwert fest. {0}

Fügen Sie schließlich ein Label Web-Steuerelement oberhalb von GridView hinzu, und legen Sie dessen ID -Eigenschaft auf ODSEvents und seine EnableViewState -Eigenschaft auf fest false. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup Ihrer Seite in etwa wie folgt aussehen. Beachten Sie, dass ich eine Reihe ästhetischer Anpassungen an den GridView-Feldern vorgenommen habe, die nicht erforderlich sind, um die SQL-Cacheabhängigkeitsfunktionalität zu demonstrieren.

<asp:Label ID="ODSEvents" runat="server" EnableViewState="False" />
<asp:GridView ID="ProductsDeclarative" runat="server" 
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSourceDeclarative" 
    AllowPaging="True" AllowSorting="True">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
            <EditItemTemplate>
                <asp:TextBox ID="ProductName" runat="server" 
                    Text='<%# Bind("ProductName") %>' />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                    ControlToValidate="ProductName" Display="Dynamic" 
                    ErrorMessage="You must provide a name for the product." 
                    SetFocusOnError="True"
                    runat="server">*</asp:RequiredFieldValidator>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>' />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
            <EditItemTemplate>
                $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                    Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
                <asp:CompareValidator ID="CompareValidator1" runat="server" 
                    ControlToValidate="UnitPrice"
                    ErrorMessage="You must enter a valid currency value with 
                        no currency symbols. Also, the value must be greater than 
                        or equal to zero."
                    Operator="GreaterThanEqual" SetFocusOnError="True" 
                    Type="Currency" Display="Dynamic" 
                    ValueToCompare="0">*</asp:CompareValidator>
            </EditItemTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("UnitPrice", "{0:c}") %>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceDeclarative" runat="server" 
    SelectMethod="GetProducts" TypeName="ProductsBLL" 
    UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Erstellen Sie als Nächstes einen Ereignishandler für das ObjectDataSource-Ereignis, Selecting und fügen Sie darin den folgenden Code hinzu:

protected void ProductsDataSourceDeclarative_Selecting
    (object sender, ObjectDataSourceSelectingEventArgs e)
{
    ODSEvents.Text = "-- Selecting event fired";
}

Denken Sie daran, dass das ObjectDataSource-Ereignis Selecting nur ausgelöst wird, wenn Daten aus dem zugrunde liegenden Objekt abgerufen werden. Wenn objectDataSource aus einem eigenen Cache auf die Daten zugreift, wird dieses Ereignis nicht ausgelöst.

Besuchen Sie diese Seite nun über einen Browser. Da wir noch keine Zwischenspeicherung implementieren müssen, sollte jedes Mal, wenn Sie das Raster anzeigen, sortieren oder bearbeiten, der Text 'Auswahlereignis ausgelöst, wie in Abbildung 8 dargestellt.

Das Selecting-Ereignis objectDataSource wird jedes Mal ausgelöst, wenn die GridView ausgelagert, bearbeitet oder sortiert wird.

Abbildung 8: Das ObjectDataSource-Ereignis Selecting wird jedes Mal ausgelöst, wenn die GridView ausgelagert, bearbeitet oder sortiert ist (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wie wir im Tutorial Zwischenspeichern von Daten mit dem ObjectDataSource-Tutorial gesehen haben, bewirkt das Festlegen der EnableCaching Eigenschaft auf true , dass die ObjectDataSource ihre Daten für die von der CacheDuration -Eigenschaft angegebene Dauer zwischenspeichert. Die ObjectDataSource verfügt außerdem über eine SqlCacheDependency -Eigenschaft, die den zwischengespeicherten Daten mithilfe des Musters eine oder mehrere SQL-Cacheabhängigkeiten hinzufügt:

databaseName1:tableName1;databaseName2:tableName2;...

Dabei ist databaseName der Name der Datenbank, wie im name Attribut des <add> Elements in Web.configangegeben, und tableName ist der Name der Datenbanktabelle. Um beispielsweise eine ObjectDataSource zu erstellen, die Daten basierend auf einer SQL-Cacheabhängigkeit mit der Tabelle Northwind s Products unbegrenzt zwischenspeichert, legen Sie die ObjectDataSource-Eigenschaft EnableCaching auf true und ihre SqlCacheDependency Eigenschaft auf NorthwindDB:Products fest.

Hinweis

Sie können eine SQL-Cacheabhängigkeit und einen zeitbasierten Ablauf verwenden, indem Sie auf true, CacheDuration auf das Zeitintervall und SqlCacheDependency auf die Datenbank- und Tabellennamen festlegenEnableCaching. Die ObjectDataSource entfernt ihre Daten, wenn der zeitbasierte Ablauf erreicht ist oder wenn das Abrufsystem feststellt, dass sich die zugrunde liegenden Datenbankdaten geändert haben, je nachdem, was zuerst geschieht.

Die GridView in SqlCacheDependencies.aspx zeigt Daten aus zwei Tabellen an – Products und Categories (das Feld des CategoryName Produkts wird über ein JOINCategoriesabgerufen). Daher möchten wir zwei SQL-Cacheabhängigkeiten angeben: NorthwindDB:Products; NorthwindDB:Categories .

Konfigurieren der ObjectDataSource zur Unterstützung der Zwischenspeicherung mithilfe von SQL Cache-Abhängigkeiten für Produkte und Kategorien

Abbildung 9: Konfigurieren der ObjectDataSource zur Unterstützung der Zwischenspeicherung mithilfe von SQL Cache-Abhängigkeiten auf Products und Categories (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Nachdem Sie objectDataSource so konfiguriert haben, dass die Zwischenspeicherung unterstützt wird, rufen Sie die Seite über einen Browser erneut auf. Auch hier sollte der Text "Ereignis auswählen" auf der ersten Seite angezeigt werden, sollte aber beim Paging, Sortieren oder Klicken auf die Schaltflächen Bearbeiten oder Abbrechen verschwinden. Dies liegt daran, dass die Daten nach dem Laden in den Cache von ObjectDataSource dort verbleiben, bis die Products Tabellen oder Categories geändert oder die Daten über GridView aktualisiert werden.

Nachdem Sie das Raster durchlaufen und das Fehlen des durch das Ereignis ausgelösten Texts feststellen, öffnen Sie ein neues Browserfenster, und navigieren Sie zum Tutorial Grundlagen im Abschnitt Bearbeiten, Einfügen und Löschen (~/EditInsertDelete/Basics.aspx). Aktualisieren Sie den Namen oder Preis eines Produkts. Zeigen Sie dann im ersten Browserfenster eine andere Datenseite an, sortieren Sie das Raster, oder klicken Sie auf die Schaltfläche Bearbeiten in einer Zeile. Dieses Mal sollte das ausgelöste Ereignis "Auswahl" erneut angezeigt werden, da die zugrunde liegenden Datenbankdaten geändert wurden (siehe Abbildung 10). Wenn der Text nicht angezeigt wird, warten Sie einige Augenblicke, und versuchen Sie es erneut. Denken Sie daran, dass der Abrufdienst alle pollTime Millisekunden nach Änderungen an der Products Tabelle sucht, sodass es zwischen dem Aktualisieren der zugrunde liegenden Daten und dem Entfernen der zwischengespeicherten Daten zu einer Verzögerung kommt.

Durch Ändern der Tabelle

Abbildung 10: Ändern der Products-Tabelle entfernt die zwischengespeicherten Produktdaten (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Schritt 6: Programmgesteuertes Arbeiten mit derSqlCacheDependency-Klasse

Im Tutorial Zum Zwischenspeichern von Daten im Architektur-Tutorial wurden die Vorteile der Verwendung einer separaten Cacheebene in der Architektur im Gegensatz zur engen Kopplung der Zwischenspeicherung mit objectDataSource untersucht. In diesem Tutorial haben wir eine ProductsCL Klasse erstellt, um das programmgesteuerte Arbeiten mit dem Datencache zu veranschaulichen. Verwenden Sie die SqlCacheDependency -Klasse, um SQL-Cacheabhängigkeiten in der Cacheebene zu verwenden.

Mit dem Abrufsystem muss ein SqlCacheDependency Objekt einem bestimmten Datenbank- und Tabellenpaar zugeordnet werden. Der folgende Code erstellt beispielsweise ein SqlCacheDependency -Objekt basierend auf der Tabelle der Northwind-Datenbank Products :

Caching.SqlCacheDependency productsTableDependency = 
    new Caching.SqlCacheDependency("NorthwindDB", "Products");

Die beiden Eingabeparameter für den SqlCacheDependency s-Konstruktor sind die Datenbank- bzw. Tabellennamen. Wie bei der ObjectDataSource-Eigenschaft SqlCacheDependency entspricht der verwendete Datenbankname dem wert, der name im -Attribut des <add> -Elements in Web.configangegeben ist. Der Tabellenname ist der tatsächliche Name der Datenbanktabelle.

Um einem SqlCacheDependency element zuzuordnen, das dem Datencache hinzugefügt wurde, verwenden Sie eine der Methodenüberladungen, die Insert eine Abhängigkeit akzeptiert. Der folgende Code fügt dem Datencache auf unbestimmte Zeit einen Wert hinzu, ordnet ihn jedoch einem SqlCacheDependency in der Products Tabelle zu. Kurz gesagt, der Wert verbleibt im Cache, bis er aufgrund von Speichereinschränkungen entfernt wird oder weil das Abrufsystem erkannt hat, dass sich die Tabelle seit der Products Zwischenspeicherung geändert hat.

Caching.SqlCacheDependency productsTableDependency = 
    new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key, 
             value, 
             productsTableDependency, 
             System.Web.Caching.Cache.NoAbsoluteExpiration, 
             System.Web.Caching.Cache.NoSlidingExpiration);

Die Caching Layer-Klasse ProductsCL speichert derzeit Daten aus der Products Tabelle unter Verwendung eines zeitbasierten Ablaufs von 60 Sekunden zwischen. Lassen Sie diese Klasse aktualisieren, sodass sie stattdessen SQL-Cacheabhängigkeiten verwendet. Die ProductsCL Methode s AddCacheItem der Klasse, die für das Hinzufügen der Daten zum Cache zuständig ist, enthält derzeit den folgenden Code:

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Make sure MasterCacheKeyArray[0] is in the cache
    DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
    // Add a CacheDependency
    Caching.CacheDependency dependency =
        new Caching.CacheDependency(null, MasterCacheKeyArray);
    DataCache.Insert(GetCacheKey(rawKey), value, dependency, 
        DateTime.Now.AddSeconds(CacheDuration), 
        System.Web.Caching.Cache.NoSlidingExpiration);
}

Aktualisieren Sie diesen Code, um ein SqlCacheDependency -Objekt anstelle der MasterCacheKeyArray Cacheabhängigkeit zu verwenden:

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Add the SqlCacheDependency objects for Products
    Caching.SqlCacheDependency productsTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Products");
    // Add the item to the data cache using productsTableDependency
    DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency, 
        Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}

Um diese Funktionalität zu testen, fügen Sie der Seite unter der vorhandenen ProductsDeclarative GridView eine GridView hinzu. Legen Sie diese neuen GridViews ID auf ProductsProgrammatic fest, und binden Sie sie über das Smarttag an eine neue ObjectDataSource namens ProductsDataSourceProgrammatic. Konfigurieren Sie objectDataSource für die Verwendung der ProductsCL -Klasse, und legen Sie die Dropdownlisten auf den Registerkarten SELECT und UPDATE auf bzwUpdateProduct. festGetProducts.

Konfigurieren der ObjectDataSource für die Verwendung der ProductsCL-Klasse

Abbildung 11: Konfigurieren der ObjectDataSource für die Verwendung der ProductsCL -Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wählen Sie die GetProducts-Methode aus der Drop-Down-Liste der REGISTERKARTEN AUSWÄHLEN aus.

Abbildung 12: Wählen Sie die GetProducts -Methode aus der Drop-Down-Liste der REGISTERKARTEN AUSWÄHLEN aus (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Wählen Sie die UpdateProduct-Methode aus der Drop-Down Liste der Registerkarten

Abbildung 13: Auswählen der UpdateProduct-Methode aus der Drop-Down Liste der Registerkarten "UPDATE" (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

Nach Abschluss des Assistenten zum Konfigurieren von Datenquellen erstellt Visual Studio boundFields und CheckBoxFields in GridView für jedes der Datenfelder. Entfernen Sie wie beim ersten Hinzugefügten GridView auf dieser Seite alle Felder außer ProductName, CategoryNameund UnitPriceund formatieren Sie diese Felder nach Bedarf. Aktivieren Sie im Smarttag von GridView die Kontrollkästchen Paging aktivieren, Sortierung aktivieren und Bearbeitung aktivieren. Wie bei ObjectDataSource ProductsDataSourceDeclarative legt Visual Studio die ProductsDataSourceProgrammatic ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf fest original_{0}. Damit die Bearbeitungsfunktion von GridView ordnungsgemäß funktioniert, legen Sie diese Eigenschaft wieder auf {0} fest (oder entfernen Sie die Eigenschaftszuweisung vollständig aus der deklarativen Syntax).

Nach Abschluss dieser Aufgaben sollte das resultierende deklarative GridView- und ObjectDataSource-Markup wie folgt aussehen:

<asp:GridView ID="ProductsProgrammatic" runat="server" 
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSourceProgrammatic" AllowPaging="True" 
    AllowSorting="True">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
            <EditItemTemplate>
                <asp:TextBox ID="ProductName" runat="server" 
                    Text='<%# Bind("ProductName") %>' />
                <asp:RequiredFieldValidator ID="RequiredFieldValidator1"  
                    ControlToValidate="ProductName" Display="Dynamic" 
                    ErrorMessage="You must provide a name for the product." 
                    SetFocusOnError="True"
                    runat="server">*</asp:RequiredFieldValidator>
            </EditItemTemplate>
            <ItemTemplate>
                <asp:Label ID="Label2" runat="server" 
                    Text='<%# Bind("ProductName") %>' />
            </ItemTemplate>
        </asp:TemplateField>
        <asp:BoundField DataField="CategoryName" HeaderText="Category" 
            ReadOnly="True" SortExpression="CategoryName" />
        <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
            <EditItemTemplate>
                $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                    Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
                <asp:CompareValidator ID="CompareValidator1" runat="server" 
                    ControlToValidate="UnitPrice" Display="Dynamic" 
                    ErrorMessage="You must enter a valid currency value with 
                        no currency symbols. Also, the value must be greater than 
                        or equal to zero."
                    Operator="GreaterThanEqual" SetFocusOnError="True" 
                    Type="Currency" ValueToCompare="0">*</asp:CompareValidator>
            </EditItemTemplate>
            <ItemStyle HorizontalAlign="Right" />
            <ItemTemplate>
                <asp:Label ID="Label1" runat="server" 
                    Text='<%# Bind("UnitPrice", "{0:c}") %>' />
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSourceProgrammatic" runat="server" 
    OldValuesParameterFormatString="{0}" SelectMethod="GetProducts" 
    TypeName="ProductsCL" UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Um die SQL-Cacheabhängigkeit in der Cacheebene zu testen, legen Sie einen Haltepunkt in der ProductCL Klasse s-Methode AddCacheItem fest, und starten Sie dann das Debuggen. Wenn Sie zum ersten Mal besuchen SqlCacheDependencies.aspx, sollte der Haltepunkt erreicht werden, wenn die Daten zum ersten Mal angefordert und im Cache platziert werden. Wechseln Sie als Nächstes zu einer anderen Seite in GridView, oder sortieren Sie eine der Spalten. Dies führt dazu, dass gridView die Daten erneut abfragen, aber die Daten sollten im Cache gefunden werden, da die Products Datenbanktabelle nicht geändert wurde. Wenn die Daten wiederholt nicht im Cache gefunden werden, stellen Sie sicher, dass auf Ihrem Computer genügend Arbeitsspeicher verfügbar ist, und versuchen Sie es erneut.

Nachdem Sie einige Seiten von GridView durchlaufen haben, öffnen Sie ein zweites Browserfenster, und navigieren Sie zum Tutorial Grundlagen im Abschnitt Bearbeiten, Einfügen und Löschen (~/EditInsertDelete/Basics.aspx). Aktualisieren Sie einen Datensatz aus der Tabelle Products, und zeigen Sie dann im ersten Browserfenster eine neue Seite an, oder klicken Sie auf eine der Sortierheader.

In diesem Szenario wird eine von zwei Dingen angezeigt: Entweder wird der Haltepunkt erreicht, was angibt, dass die zwischengespeicherten Daten aufgrund der Änderung in der Datenbank entfernt wurden. oder der Haltepunkt wird nicht erreicht, was bedeutet, dass SqlCacheDependencies.aspx jetzt veraltete Daten angezeigt werden. Wenn der Haltepunkt nicht erreicht wird, liegt dies wahrscheinlich daran, dass der Abrufdienst noch nicht ausgelöst wurde, seit die Daten geändert wurden. Denken Sie daran, dass der Abrufdienst alle pollTime Millisekunden nach Änderungen an der Products Tabelle sucht, sodass es zwischen dem Aktualisieren der zugrunde liegenden Daten und dem Entfernen der zwischengespeicherten Daten zu einer Verzögerung kommt.

Hinweis

Diese Verzögerung tritt eher beim Bearbeiten eines der Produkte über gridView in auf SqlCacheDependencies.aspx. Im Tutorial Zum Zwischenspeichern von Daten im Architekturtutorial wurde die MasterCacheKeyArray Cacheabhängigkeit hinzugefügt, um sicherzustellen, dass die Daten, die über die Methode der ProductsCL Klasse s UpdateProduct bearbeitet werden, aus dem Cache entfernt wurden. Wir haben diese Cacheabhängigkeit jedoch beim Ändern der AddCacheItem Methode weiter oben in diesem Schritt ersetzt. Daher zeigt die ProductsCL Klasse weiterhin die zwischengespeicherten Daten an, bis das Abrufsystem die Änderung an der Products Tabelle notiert. In Schritt 7 erfahren Sie, wie Sie die MasterCacheKeyArray Cacheabhängigkeit wiedereinführen.

Schritt 7: Zuordnen mehrerer Abhängigkeiten zu einem zwischengespeicherten Element

Denken Sie daran, dass die MasterCacheKeyArray Cacheabhängigkeit verwendet wird, um sicherzustellen, dass alle produktbezogenen Daten aus dem Cache entfernt werden, wenn ein einzelnes element, das darin zugeordnet ist, aktualisiert wird. Die -Methode speichert z. GetProductsByCategoryID(categoryID) B. Instanzen für jeden eindeutigen ProductsDataTablescategoryID-Wert zwischen. Wenn eines dieser Objekte entfernt wird, stellt die MasterCacheKeyArray Cacheabhängigkeit sicher, dass auch die anderen entfernt werden. Ohne diese Cacheabhängigkeit besteht beim Ändern der zwischengespeicherten Daten die Möglichkeit, dass andere zwischengespeicherte Produktdaten veraltet sind. Daher ist es wichtig, dass wir die MasterCacheKeyArray Cacheabhängigkeit beibehalten, wenn SQL-Cacheabhängigkeiten verwendet werden. Die Methode s des Datencaches Insert lässt jedoch nur ein einzelnes Abhängigkeitsobjekt zu.

Darüber hinaus müssen wir bei der Arbeit mit SQL-Cacheabhängigkeiten möglicherweise mehrere Datenbanktabellen als Abhängigkeiten zuordnen. Die in der ProductsDataTableProductsCL -Klasse zwischengespeicherte enthält beispielsweise die Kategorie- und Lieferantennamen für jedes Produkt, die Methode verwendet jedoch AddCacheItem nur eine Abhängigkeit von Products. Wenn der Benutzer in diesem Fall den Namen einer Kategorie oder eines Lieferanten aktualisiert, verbleiben die zwischengespeicherten Produktdaten im Cache und sind veraltet. Daher möchten wir die zwischengespeicherten Produktdaten nicht nur von der Products Tabelle, sondern auch von den Categories Tabellen und Suppliers abhängig machen.

Die AggregateCacheDependency -Klasse bietet ein Mittel zum Zuordnen mehrerer Abhängigkeiten zu einem Cacheelement. Erstellen Sie zunächst eine AggregateCacheDependency instance. Fügen Sie als Nächstes den Satz von Abhängigkeiten mithilfe der AggregateCacheDependency s-Methode Add hinzu. Wenn Sie das Element anschließend in den Datencache einfügen, übergeben Sie die AggregateCacheDependency instance. Wenn sich eine der AggregateCacheDependency instance Abhängigkeiten ändert, wird das zwischengespeicherte Element entfernt.

Im Folgenden wird der aktualisierte Code für die Methode s der ProductsCL Klasse gezeigt AddCacheItem . Die -Methode erstellt die MasterCacheKeyArray Cacheabhängigkeit zusammen mit SqlCacheDependency -Objekten für die ProductsTabellen , Categoriesund Suppliers . Diese werden alle in einem AggregateCacheDependency Objekt namens aggregateDependencieskombiniert, das dann an die Insert -Methode übergeben wird.

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Make sure MasterCacheKeyArray[0] is in the cache and create a depedency
    DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
    Caching.CacheDependency masterCacheKeyDependency = 
        new Caching.CacheDependency(null, MasterCacheKeyArray);
    // Add the SqlCacheDependency objects for Products, Categories, and Suppliers
    Caching.SqlCacheDependency productsTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Products");
    Caching.SqlCacheDependency categoriesTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Categories");
    Caching.SqlCacheDependency suppliersTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Suppliers");
    // Create an AggregateCacheDependency
    Caching.AggregateCacheDependency aggregateDependencies = 
        new Caching.AggregateCacheDependency();
    aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency, 
        categoriesTableDependency, suppliersTableDependency);
    DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies, 
        Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}

Testen Sie diesen neuen Code. Änderungen an den ProductsTabellen , oder Suppliers führen nun dazu, Categoriesdass die zwischengespeicherten Daten entfernt werden. Darüber hinaus entfernt die ProductsCL S-Methode der Klasse UpdateProduct , die beim Bearbeiten eines Produkts über gridView aufgerufen wird, die MasterCacheKeyArray Cacheabhängigkeit, wodurch die zwischengespeicherte ProductsDataTable entfernt und die Daten bei der nächsten Anforderung erneut abgerufen werden.

Hinweis

SQL-Cacheabhängigkeiten können auch mit der Ausgabezwischenspeicherung verwendet werden. Eine Demonstration dieser Funktionalität finden Sie unter Verwenden ASP.NET Ausgabezwischenspeicherung mit SQL Server.

Zusammenfassung

Beim Zwischenspeichern von Datenbankdaten verbleiben die Daten im Idealfall im Cache, bis sie in der Datenbank geändert werden. Mit ASP.NET 2.0 können SQL-Cacheabhängigkeiten erstellt und sowohl in deklarativen als auch in programmgesteuerten Szenarien verwendet werden. Eine der Herausforderungen bei diesem Ansatz besteht darin, zu ermitteln, wann die Daten geändert wurden. Die Vollversionen von Microsoft SQL Server 2005 bieten Benachrichtigungsfunktionen, mit denen eine Anwendung benachrichtigt werden kann, wenn sich ein Abfrageergebnis geändert hat. Für die Express Edition von SQL Server 2005 und älteren Versionen von SQL Server muss stattdessen ein Abrufsystem verwendet werden. Glücklicherweise ist das Einrichten der erforderlichen Umfrageinfrastruktur ziemlich einfach.

Viel Spaß beim Programmieren!

Weitere Informationen

Weitere Informationen zu den in diesem Tutorial behandelten Themen finden Sie in den folgenden Ressourcen:

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderer Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Hauptprüfer für dieses Tutorial waren Marko Rangel, Teresa Murphy und Hilton Giesenow. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.