Verwenden von SQL-Cacheabhängigkeiten (C#)
von Scott Mitchell
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
, notificationCreated
und 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.exe
erstellt 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 pubs
ScottsServer
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 -et
anstelle 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 authors
pubs
Datenbank auf ScottsServer
hinzuzufü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 Products
Tabellen , Categories
und 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.
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
.
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.
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.MDF
App_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 Products
Tabellen , Categories
und Suppliers
.
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_SqlCacheTablesForChangeNotification
zurü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 ProductsDataSourceDeclarative
zu binden.
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
, unitPrice
und productID
aus. Legen Sie die Dropdownlisten auf den Registerkarten INSERT und DELETE auf (Keine) fest.
Abbildung 6: Verwenden der UpdateProduct-Überladung mit drei Eingabeparametern (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
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
, CategoryName
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. 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.
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.config
angegeben, 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 JOIN
Categories
abgerufen). Daher möchten wir zwei SQL-Cacheabhängigkeiten angeben: NorthwindDB:Products; NorthwindDB:Categories .
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.
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.config
angegeben 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
.
Abbildung 11: Konfigurieren der ObjectDataSource für die Verwendung der ProductsCL
-Klasse (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
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)
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
, CategoryName
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 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 ProductsDataTables
categoryID-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 ProductsDataTable
ProductsCL
-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 Products
Tabellen , Categories
und Suppliers
. Diese werden alle in einem AggregateCacheDependency
Objekt namens aggregateDependencies
kombiniert, 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 Products
Tabellen , oder Suppliers
führen nun dazu, Categories
dass 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:
- Verwenden von Abfragebenachrichtigungen in Microsoft SQL Server 2005
- Erstellen einer Abfragebenachrichtigung
- Zwischenspeichern in ASP.NET mit der
SqlCacheDependency
-Klasse - ASP.NET SQL Server-Registrierungstool (
aspnet_regsql.exe
) - Übersicht über
SqlCacheDependency
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.