Share via


Verwenden von SQL-Cacheabhängigkeiten (VB)

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 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 Datenalter 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 Abfragesystems befasst. Wenn diese Infrastruktur vorhanden 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 die deklarative Arbeit mit SQL-Cacheabhängigkeiten untersucht. In Schritt 6 sehen wir uns den programmgesteuerten Ansatz an.

Im Tutorial Zwischenspeichern von Daten mit ObjectDataSource wurden die deklarativen Zwischenspeicherungsfunktionen von ObjectDataSource untersucht. Indem Sie einfach die EnableCaching -Eigenschaft auf True und die CacheDuration -Eigenschaft auf ein bestimmtes Zeitintervall festlegen, speichert die ObjectDataSource automatisch die von ihrem zugrunde liegenden Objekt zurückgegebenen Daten für das angegebene Intervall zwischen. 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 eine GridView aus der Toolbox auf die Designer. Legen Sie die GridView s ID auf ProductsDeclarative fest, und wählen Sie aus dem Smarttag aus, um es an eine neue ObjectDataSource mit dem Namen ProductsDataSourceDeclarativezu binden.

Erstellen einer neuen ObjectDataSource namens ProductsDataSourceDeclarative

Abbildung 5: Erstellen eines 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, 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 Datenfeld. Entfernen Sie alle Felder außer ProductName, CategoryNameund , und UnitPriceformatieren 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 die Bearbeitungsfunktion 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 über der GridView hinzu, und legen Sie seine ID Eigenschaft auf ODSEvents und seine EnableViewState Eigenschaft auf Falsefest. Nachdem Sie diese Änderungen vorgenommen haben, sollte das deklarative Markup Ihrer Seite wie folgt aussehen. Beachten Sie, dass ich eine Reihe von ästhetischen Anpassungen an die GridView-Felder 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 Sub ProductsDataSourceDeclarative_Selecting _
    (sender As Object, e As ObjectDataSourceSelectingEventArgs) _
    Handles ProductsDataSourceDeclarative.Selecting
    ODSEvents.Text = "-- Selecting event fired"
End Sub

Denken Sie daran, dass das ObjectDataSource-Ereignis Selecting nur beim Abrufen von Daten aus dem zugrunde liegenden Objekt ausgelöst wird. Wenn ObjectDataSource über einen 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 bei jeder Seite, Sortierung oder Bearbeitung des Rasters der Text angezeigt werden: "Ereignisauswahl ausgelöst, wie Abbildung 8 zeigt.

Das ObjektDataSource-Auswahlereignis 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 wird (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)

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

databaseName1:tableName1;databaseName2:tableName2;...

Wobei databaseName der Name der Datenbank ist, 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 von 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 für das Zeitintervall und SqlCacheDependency für 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-Cacheabhängigkeiten für Produkte und Kategorien

Abbildung 9: Konfigurieren der ObjectDataSource für die Unterstützung der Zwischenspeicherung mithilfe von SQL-Cacheabhängigkeiten auf Products und Categories (Klicken, um das bild in voller Größe anzuzeigen)

Nachdem Sie objectDataSource für die Unterstützung der Zwischenspeicherung konfiguriert haben, besuchen Sie die Seite über einen Browser erneut. 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.

Öffnen Sie nach dem Durchlaufen des Rasters und dem Fehlen des vom Ereignis ausgelösten Texts 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 der Zeile. Dieses Mal sollte das ausgelöste Ereignis "Auswahlereignis" 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 auf Änderungen an der Products Tabelle überprüft, sodass es zwischen dem Aktualisieren der zugrunde liegenden Daten und dem Entfernen der zwischengespeicherten Daten zu einer Verzögerung kommt.

Ändern der Tabelle

Abbildung 10: Ändern der Tabelle "Produkte" entfernt die zwischengespeicherten Produktdaten (Klicken, um das bild in voller Größe anzuzeigen)

Schritt 6: Programmgesteuertes Arbeiten mit derSqlCacheDependencyKlasse

Im Tutorial Zum Zwischenspeichern von Daten in der Architektur wurden die Vorteile der Verwendung einer separaten Zwischenspeicherebene in der Architektur im Gegensatz zur engen Kopplung der Zwischenspeicherung mit der 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 Zwischenspeicherebene zu verwenden.

Beim Abrufsystem muss ein SqlCacheDependency Objekt einem bestimmten Datenbank- und Tabellenpaar zugeordnet sein. Mit dem folgenden Code wird beispielsweise ein SqlCacheDependency Objekt basierend auf der Tabelle der Northwind-Datenbank Products erstellt:

Dim productsTableDependency As _
    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 ist der verwendete Datenbankname mit dem im Attribut des <add> -Elements in nameWeb.configangegebenen Wert identisch. Der Tabellenname ist der tatsächliche Name der Datenbanktabelle.

Um ein SqlCacheDependency einem 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 dem Products Zwischenspeichern geändert hat.

Dim productsTableDependency As _
    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. Aktualisieren Sie diese Klasse so, dass sie stattdessen SQL-Cacheabhängigkeiten verwendet. Die ProductsCL Methode s AddCacheItem der Klasse, die für das Hinzufügen der Daten zum Cache verantwortlich ist, enthält derzeit den folgenden Code:

Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
    ' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it
    If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
        DataCache(MasterCacheKeyArray(0)) = DateTime.Now
    End If
    ' Add a CacheDependency
    Dim dependency As _
        New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
    DataCache.Insert(GetCacheKey(rawKey), value, dependency, _
        DateTime.Now.AddSeconds(CacheDuration), _
        Caching.Cache.NoSlidingExpiration)
End Sub

Aktualisieren Sie diesen Code so, dass anstelle der MasterCacheKeyArray Cacheabhängigkeit ein SqlCacheDependency -Objekt verwendet wird:

Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
    ' Add the SqlCacheDependency objects for Products
    Dim productsTableDependency As New _
        Caching.SqlCacheDependency("NorthwindDB", "Products")
    DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency, _
        Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub

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 fest ProductsProgrammatic , und binden Sie sie über das Smarttag an eine neue ObjectDataSource mit dem Namen ProductsDataSourceProgrammatic. Konfigurieren Sie die 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 SELECT aus.

Abbildung 12: Wählen Sie die GetProducts Methode aus der Drop-Down Liste der REGISTERKARTE SELECT aus (Klicken Sie, um das bild in voller Größe anzuzeigen)

Wählen Sie die UpdateProduct-Methode aus der Drop-Down Liste der Registerkarte UPDATE aus.

Abbildung 13: Wählen Sie die UpdateProduct-Methode aus der Drop-Down Liste der REGISTERKARTE UPDATE aus (Klicken Sie, 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 Datenfeld. Entfernen Sie wie bei der ersten GridView dieser Seite alle Felder außer ProductName, CategoryNameund , und UnitPrice, und 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 Zwischenspeicherebene zu testen, legen Sie einen Haltepunkt in der Methode der ProductCL Klasse s AddCacheItem fest, und starten Sie dann das Debuggen. Beim ersten Besuch SqlCacheDependencies.aspxsollte der Haltepunkt erreicht werden, da die Daten zum ersten Mal angefordert und im Cache abgelegt werden. Wechseln Sie als Nächstes zu einer anderen Seite in GridView, oder sortieren Sie eine der Spalten. Dies führt dazu, dass gridView seine 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 der 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 sehen Sie eines von zwei Dingen: Entweder wird der Haltepunkt erreicht, der 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 auf Änderungen an der Products Tabelle überprüft, 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 die GridView in auf SqlCacheDependencies.aspx. Im Tutorial Zwischenspeichern von Daten im Architektur-Tutorial haben wir 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. Diese Cacheabhängigkeit haben wir jedoch beim Ändern der AddCacheItem Methode zuvor in diesem Schritt ersetzt. Daher zeigt die ProductsCL Klasse weiterhin die zwischengespeicherten Daten an, bis das Abfragesystem die Änderung an der Products Tabelle notiert. In Schritt 7 erfahren Sie, wie Sie die MasterCacheKeyArray Cacheabhängigkeit wieder einfü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. Beispielsweise speichert die GetProductsByCategoryID(categoryID) -Methode Instanzen für jeden eindeutigen ProductsDataTablescategoryID-Wert zwischen. Wenn eines dieser Objekte entfernt wird, stellt die MasterCacheKeyArray Cacheabhängigkeit sicher, dass die anderen objekte ebenfalls 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 Cacheabhängigkeit bei Verwendung von MasterCacheKeyArray SQL-Cacheabhängigkeiten beibehalten. Die Methode s des Datencaches Insert lässt jedoch nur ein einzelnes Abhängigkeitsobjekt zu.

Darüber hinaus müssen wir beim Arbeiten 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, aber die AddCacheItem Methode verwendet nur eine Abhängigkeit von Products. Wenn der Benutzer in dieser Situation 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 Abhängigkeiten der instance ändert, wird das zwischengespeicherte Element entfernt.

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

Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
    Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
    ' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it.
    If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
        DataCache(MasterCacheKeyArray(0)) = DateTime.Now
    End If
    'Create the CacheDependency
    Dim masterCacheKeyDependency As _
        New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
    ' Add the SqlCacheDependency objects for Products, Categories, and Suppliers
    Dim productsTableDependency As _
        New Caching.SqlCacheDependency("NorthwindDB", "Products")
    Dim categoriesTableDependency As _
        New Caching.SqlCacheDependency("NorthwindDB", "Categories")
    Dim suppliersTableDependency As _
        New Caching.SqlCacheDependency("NorthwindDB", "Suppliers")
    ' Create an AggregateCacheDependency
    Dim aggregateDependencies As New Caching.AggregateCacheDependency()
    aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency, _
        categoriesTableDependency, suppliersTableDependency)
    DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies, _
        Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub

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 Methode s UpdateProduct der ProductsCL Klasse, die beim Bearbeiten eines Produkts über gridView aufgerufen wird, die MasterCacheKeyArray Cacheabhängigkeit, wodurch die zwischengespeicherten ProductsDataTable entfernt und die Daten bei der nächsten Anforderung erneut abgerufen werden.

Hinweis

SQL-Cacheabhängigkeiten können auch beim Ausgabezwischenspeichern 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 sowohl in deklarativen als auch in programmgesteuerten Szenarien erstellt und 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, die eine Anwendung warnen können, 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 Abfragesystem verwendet werden. Glücklicherweise ist die Einrichtung der erforderlichen Umfrageinfrastruktur ziemlich einfach.

Viel Spaß beim Programmieren!

Weitere Informationen

Weitere Informationen zu den in diesem Tutorial erläuterten 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 Stunden. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderen 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 anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.