Delen via


SQL Cache-afhankelijkheden (VB) gebruiken

door Scott Mitchell

PDF downloaden

De eenvoudigste cachingstrategie is om gegevens in de cache na een bepaalde periode te laten verlopen. Maar deze eenvoudige aanpak betekent dat de gegevens in de cache geen verband houden met de onderliggende gegevensbron, wat resulteert in verouderde gegevens die te lang worden bewaard of huidige gegevens die te snel zijn verlopen. Een betere aanpak is om de klasse SqlCacheDependency te gebruiken, zodat gegevens in de cache blijven totdat de onderliggende gegevens zijn gewijzigd in de SQL-database. In deze zelfstudie leert u hoe u dit doet.

Introductie

De cachingtechnieken die worden onderzocht in de tutorials Caching Data met de ObjectDataSource en Caching Data in de Architecture-zelfstudies , gebruikten een op tijd gebaseerde vervaldatum om de gegevens na een bepaalde periode uit de cache te verwijderen. Deze aanpak is de eenvoudigste manier om de prestatiewinst van caching af te wegen tegen de veroudering van gegevens. Door een tijdsverloop van x seconden te selecteren, geeft een pagina-ontwikkelaar toe dat hij slechts x seconden kan genieten van de prestatievoordelen van caching, maar kan hij erop vertrouwen dat zijn gegevens nooit langer dan maximaal x seconden oud zullen zijn. Voor statische gegevens kan x natuurlijk worden verlengd tot de levensduur van de webtoepassing, zoals is onderzocht in de tutorial Caching Data at Application Startup .

Bij het cachen van databasegegevens wordt vaak gekozen voor een op tijd gebaseerde vervaldatum vanwege het gebruiksgemak, maar dit is vaak een ontoereikende oplossing. Idealiter blijven de databasegegevens in de cache totdat de onderliggende gegevens in de database zijn gewijzigd; Pas dan zou de cache worden ontruimd. Deze aanpak maximaliseert de prestatievoordelen van caching en minimaliseert de duur van verouderde gegevens. Om van deze voordelen te kunnen genieten, moet er echter een systeem zijn dat weet wanneer de onderliggende databasegegevens zijn gewijzigd en de bijbehorende items uit de cache verwijdert. Vóór ASP.NET 2.0 waren pagina-ontwikkelaars verantwoordelijk voor de implementatie van dit systeem.

ASP.NET 2.0 biedt een SqlCacheDependency klasse en de benodigde infrastructuur om te bepalen wanneer er een wijziging in de database is opgetreden, zodat de bijbehorende items in de cache kunnen worden verwijderd. Er zijn twee technieken om te bepalen wanneer de onderliggende gegevens zijn gewijzigd: notificatie en polling. Nadat we de verschillen tussen melding en opiniepeiling hebben besproken, maken we de infrastructuur die nodig is om peilingen te ondersteunen en onderzoeken we vervolgens hoe we de SqlCacheDependency klasse kunnen gebruiken in declaratieve en programmatische scenario's.

Inzicht in meldingen en peilingen

Er zijn twee technieken die kunnen worden gebruikt om te bepalen wanneer de gegevens in een database zijn gewijzigd: notificatie en polling. Met melding waarschuwt de database automatisch de ASP.NET runtime wanneer de resultaten van een bepaalde query zijn gewijzigd sinds de query voor het laatst is uitgevoerd, waarna de in de cache opgeslagen items die aan de query zijn gekoppeld, worden verwijderd. Bij polling houdt de databaseserver informatie bij over wanneer bepaalde tabellen voor het laatst zijn bijgewerkt. De ASP.NET runtime controleert periodiek de database om te controleren welke tabellen zijn gewijzigd sinds ze in de cache zijn ingevoerd. De bijbehorende cache-items worden verwijderd uit de tabellen waarvan de gegevens zijn gewijzigd.

De meldingsoptie vereist minder instellingen dan polling en is gedetailleerder omdat wijzigingen op queryniveau worden bijgehouden in plaats van op tabelniveau. Helaas zijn meldingen alleen beschikbaar in de volledige edities van Microsoft SQL Server 2005 (d.w.z. de niet-Express-edities). De polling-optie kan echter worden gebruikt voor alle versies van Microsoft SQL Server van 7.0 tot 2005. Aangezien in deze zelfstudies gebruikmaakt van de Express-editie van SQL Server 2005, richten we ons op het instellen en gebruiken van de polling-optie. Raadpleeg de sectie Verder lezen aan het einde van deze zelfstudie voor meer informatie over de meldingsmogelijkheden van SQL Server 2005.

Bij peilingen moet de database worden geconfigureerd om een tabel met de naam AspNet_SqlCacheTablesForChangeNotification op te nemen die drie kolommen tableNamebevat: , notificationCreated, en changeId. Deze tabel bevat een rij voor elke tabel met gegevens die mogelijk moeten worden gebruikt in een SQL-cacheafhankelijkheid in de webtoepassing. De tableName kolom geeft de naam van de tabel aan en notificationCreated geeft de datum en tijd aan waarop de rij aan de tabel is toegevoegd. De changeId kolom is van het type int en heeft een beginwaarde van 0. De waarde wordt verhoogd bij elke wijziging in de tabel.

Naast de AspNet_SqlCacheTablesForChangeNotification tabel moet de database ook triggers bevatten voor elk van de tabellen die kunnen worden weergegeven in een SQL-cacheafhankelijkheid. Deze triggers worden uitgevoerd wanneer een rij wordt ingevoegd, bijgewerkt of verwijderd en verhogen de waarde van changeId de tabel in AspNet_SqlCacheTablesForChangeNotification.

De ASP.NET runtime houdt de stroom changeId voor een tabel bij bij het cachen van gegevens met behulp van een SqlCacheDependency object. De database wordt periodiek gecontroleerd en alle SqlCacheDependency objecten waarvan changeId de waarde in de database afwijkt, worden verwijderd omdat een afwijkende changeId waarde aangeeft dat de tabel is gewijzigd sinds de gegevens in de cache zijn opgeslagen.

Stap 1: Het opdrachtregelprogramma verkennenaspnet_regsql.exe

Met de polling-benadering moet de database worden ingesteld om de hierboven beschreven infrastructuur te bevatten: een vooraf gedefinieerde tabel (AspNet_SqlCacheTablesForChangeNotification), een handvol opgeslagen procedures en triggers op elk van de tabellen die kunnen worden gebruikt in SQL-cache-afhankelijkheden in de webtoepassing. Deze tabellen, opgeslagen procedures en triggers kunnen worden gemaakt via het opdrachtregelprogramma aspnet_regsql.exe, dat zich in de $WINDOWS$\Microsoft.NET\Framework\version map bevindt. Als u de tabel en de AspNet_SqlCacheTablesForChangeNotification bijbehorende opgeslagen procedures wilt maken, voert u het volgende uit vanaf de opdrachtregel:

/* 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

Opmerking

Om deze opdrachten uit te voeren, moet de opgegeven database-login zich in de db_securityadmin rollen en db_ddladmin bevinden.

Als u bijvoorbeeld de infrastructuur voor opiniepeilingen wilt toevoegen aan een Microsoft SQL Server-database met de naam pubs op een databaseserver met de naam ScottsServer Windows-verificatie, navigeert u naar de juiste map en voert u vanaf de opdrachtregel het volgende in:

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

Nadat de infrastructuur op databaseniveau is toegevoegd, moeten we de triggers toevoegen aan de tabellen die worden gebruikt in SQL-cache-afhankelijkheden. Gebruik het aspnet_regsql.exe opdrachtregelprogramma opnieuw, maar geef de tabelnaam op met behulp van de -t schakelaar en gebruik -edin plaats van de -et schakelaar , als volgt:

/* 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

Als u de triggers wilt toevoegen aan de authors en titles tabellen in de pubs database op ScottsServer, gebruikt:

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

Voeg voor deze zelfstudie de triggers toe aan de Products, Categories, en Suppliers tabellen. We zullen kijken naar de specifieke opdrachtregelsyntaxis in stap 3.

Stap 2: Verwijzen naar een Microsoft SQL Server 2005 Express Edition-database inApp_Data

Het aspnet_regsql.exe opdrachtregelprogramma vereist de database- en servernaam om de benodigde polling-infrastructuur toe te voegen. Maar wat is de database- en servernaam voor een Microsoft SQL Server 2005 Express-database die zich in de App_Data map bevindt? In plaats van te moeten ontdekken wat de database- en servernamen zijn, heb ik ontdekt dat de eenvoudigste aanpak is om de database aan de localhost\SQLExpress database-instantie toe te voegen en de gegevens te hernoemen met behulp van SQL Server Management Studio. Als u een van de volledige versies van SQL Server 2005 op uw computer hebt geïnstalleerd, is SQL Server Management Studio waarschijnlijk al op uw computer geïnstalleerd. Als u alleen de Express-editie hebt, kunt u de gratis Microsoft SQL Server Management Studio downloaden.

Begin met het sluiten van Visual Studio. Open vervolgens SQL Server Management Studio en kies ervoor om verbinding te maken met de localhost\SQLExpress server met behulp van Windows-verificatie.

Koppelen aan de localhost\SQLExpress Server

Afbeelding 1: Aansluiten op de localhost\SQLExpress server

Nadat u verbinding hebt gemaakt met de server, toont Management Studio de server en heeft het submappen voor de databases, beveiliging, enzovoort. Klik met de rechtermuisknop op de map Databases en kies de optie Bijvoegen. Hierdoor wordt het dialoogvenster Databases bijvoegen geopend (zie afbeelding 2). Klik op de knop Toevoegen en selecteer de databasemap in de NORTHWND.MDF map van App_Data uw webtoepassing.

Bevestig de NORTHWND. MDF-database uit de map App_Data

Afbeelding 2: Voeg de NORTHWND.MDF database toe vanuit de App_Data map (klik om de afbeelding op volledige grootte te bekijken)

Hiermee wordt de database toegevoegd aan de map Databases. De databasenaam kan het volledige pad naar het databasebestand zijn of het volledige pad dat wordt voorafgegaan door een GUID. Om te voorkomen dat u deze lange databasenaam moet typen wanneer u de opdrachtregeltool aspnet_regsql.exe gebruikt, wijzigt u de naam van de database naar een meer mensvriendelijke naam door met de rechtermuisknop op de zojuist bijgevoegde database te klikken en Naam wijzigen te kiezen. Ik heb mijn database hernoemd naar DataTutorials.

Wijzig de naam van de bijgevoegde database in een meer Human-Friendly naam

Figuur 3: Hernoem de bijgevoegde database naar een meer Human-Friendly naam

Stap 3: De polling-infrastructuur toevoegen aan de Northwind-database

Nu we de NORTHWND.MDF database uit de App_Data map hebben bijgevoegd, zijn we klaar om de polling-infrastructuur toe te voegen. Ervan uitgaande dat u de naam van de database hebt gewijzigd in DataTutorials, voert u de volgende vier opdrachten uit:

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

Nadat u deze vier opdrachten hebt uitgevoerd, klikt u met de rechtermuisknop op de databasenaam in Management Studio, gaat u naar het submenu Taken en kiest u Loskoppelen. Sluit vervolgens Management Studio en open Visual Studio opnieuw.

Zodra Visual Studio opnieuw is geopend, zoomt u in op de database via de Server Explorer. Noteer de nieuwe tabel (AspNet_SqlCacheTablesForChangeNotification), de nieuwe opgeslagen procedures en de triggers op de Products, Categories, en Suppliers tabellen.

De database bevat nu de benodigde polling-infrastructuur

Figuur 4: De database bevat nu de benodigde polling-infrastructuur

Stap 4: De stembureau configureren

Na het maken van de benodigde tabellen, triggers en opgeslagen procedures in de database, is de laatste stap het configureren van de pollingservice, wat wordt gedaan Web.config door de te gebruiken databases en de pollingfrequentie in milliseconden op te geven. De volgende opmaak peilt de Noordenwind-database eens per seconde.

<?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>

De name waarde in het <add> element ( NorthwindDB ) associeert een voor mensen leesbare naam met een bepaalde database. Wanneer u met SQL-cacheafhankelijkheden werkt, moeten we verwijzen naar de databasenaam die hier is gedefinieerd, evenals de tabel waarop de gegevens in de cache zijn gebaseerd. In stap 6 zien we hoe we de SqlCacheDependency klasse kunnen gebruiken om SQL-cacheafhankelijkheden programmatisch te koppelen aan gegevens in de cache.

Zodra een SQL-cacheafhankelijkheid tot stand is gebracht, maakt het pollingsysteem elke <databases> milliseconden verbinding met de databases die in de pollTime elementen zijn gedefinieerd en voert het de AspNet_SqlCachePollingStoredProcedure opgeslagen procedure uit. Deze opgeslagen procedure, die in stap 3 weer is toegevoegd met behulp van de aspnet_regsql.exe opdrachtregel, retourneert de tableName en-waarden changeId voor elke record in AspNet_SqlCacheTablesForChangeNotification. Verouderde SQL-cacheafhankelijkheden worden uit de cache verwijderd.

De pollTime instelling introduceert een afweging tussen prestaties en veroudering van gegevens. Een kleine pollTime waarde verhoogt het aantal verzoeken aan de database, maar verwijdert sneller verouderde gegevens uit de cache. Een grotere pollTime waarde vermindert het aantal databaseaanvragen, maar verhoogt de vertraging tussen het moment waarop de back-endgegevens worden gewijzigd en het moment waarop de gerelateerde cache-items worden verwijderd. Gelukkig voert het databaseverzoek een eenvoudige opgeslagen procedure uit die slechts een paar rijen retourneert uit een eenvoudige, lichtgewicht tabel. Maar experimenteer wel met verschillende pollTime waarden om een ideale balans te vinden tussen databasetoegang en dataveroudering voor uw toepassing. De kleinst pollTime toegestane waarde is 500.

Opmerking

In het bovenstaande voorbeeld vindt u één pollTime waarde in het <sqlCacheDependency> element, maar u kunt de pollTime waarde desgewenst in het <add> element opgeven. Dit is handig als u meerdere databases hebt opgegeven en de pollingfrequentie per database wilt aanpassen.

Stap 5: Declaratief werken met SQL Cache Dependencies

In stap 1 tot en met 4 hebben we gekeken hoe we de benodigde database-infrastructuur kunnen opzetten en het stemsysteem kunnen configureren. Met deze infrastructuur kunnen we nu items toevoegen aan de gegevenscache met een bijbehorende SQL-cacheafhankelijkheid met behulp van programmatische of declaratieve technieken. In deze stap onderzoeken we hoe u declaratief kunt werken met SQL-cache-afhankelijkheden. In stap 6 kijken we naar de programmatische aanpak.

In de zelfstudie Caching Data met de ObjectDataSource werden de declaratieve cachingmogelijkheden van de ObjectDataSource verkend. Door simpelweg de EnableCaching eigenschap in te stellen op True en de CacheDuration eigenschap op een bepaald tijdsinterval, zal de ObjectDataSource de gegevens die worden geretourneerd van het onderliggende object automatisch in de cache opslaan voor het opgegeven interval. De ObjectDataSource kan ook gebruikmaken van een of meer SQL-cache-afhankelijkheden.

Als u het gebruik van SQL-cacheafhankelijkheden declaratief wilt demonstreren, opent u de SqlCacheDependencies.aspx pagina in de Caching map en sleept u een GridView van de Werkset naar de Ontwerper. Stel de ID van de GridView in op ProductsDeclarative en kies vervolgens via het slimme label om deze te koppelen aan een nieuwe ObjectDataSource met de naam ProductsDataSourceDeclarative.

Een nieuw object makenDataSource met de naam ProductsDataSourceDeclarative

Afbeelding 5: Een nieuwe ObjectDataSource maken met de naam ProductsDataSourceDeclarative (klik om de afbeelding op volledige grootte weer te geven)

Configureer de ObjectDataSource voor het gebruik van de ProductsBLL klasse en stel de vervolgkeuzelijst op het tabblad SELECT in op GetProducts(). Kies op het tabblad UPDATE de UpdateProduct overbelasting met drie invoerparameters - productName, unitPrice, en productID. Stel de vervolgkeuzelijsten in op (Geen) op de tabbladen INVOEGEN en VERWIJDEREN.

Gebruik de UpdateProduct Overload met drie invoerparameters

Afbeelding 6: Gebruik de UpdateProduct Overload met drie invoerparameters (klik om de afbeelding op volledige grootte te bekijken)

Stel de lijst met Drop-Down in op (Geen) voor de tabbladen INVOEGEN en VERWIJDEREN

Afbeelding 7: Stel de lijst met Drop-Down in op (Geen) voor de tabbladen INVOEGEN en VERWIJDEREN (klik om de afbeelding op volledige grootte weer te geven)

Na het voltooien van de wizard Gegevensbron configureren, maakt Visual Studio BoundFields en CheckBoxFields in de GridView voor elk van de gegevensvelden. Verwijder alle velden behalve ProductName, CategoryName, en UnitPrice, en maak deze velden naar eigen inzicht op. Schakel in de infocode van GridView de selectievakjes Paging inschakelen, Sorteren inschakelen en Bewerken inschakelen in. Visual Studio stelt de eigenschap van ObjectDataSource in OldValuesParameterFormatString op original_{0}. Om ervoor te zorgen dat de bewerkingsfunctie van GridView goed werkt, verwijdert u deze eigenschap volledig uit de declaratieve syntaxis of zet u deze terug op de standaardwaarde, {0}.

Voeg ten slotte een besturingselement Label Web toe boven de GridView en stel de eigenschap in op ID en ODSEvents de EnableViewState eigenschap op False. Nadat u deze wijzigingen heeft aangebracht, moet de declaratieve opmaak van uw pagina er ongeveer als volgt uitzien. Houd er rekening mee dat ik een aantal esthetische aanpassingen heb aangebracht in de GridView-velden die niet nodig zijn om de functionaliteit voor SQL-cacheafhankelijkheid te demonstreren.

<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>

Maak vervolgens een gebeurtenis-handler voor de gebeurtenis van Selecting ObjectDataSource en voeg daarin de volgende code toe:

Protected Sub ProductsDataSourceDeclarative_Selecting _
    (sender As Object, e As ObjectDataSourceSelectingEventArgs) _
    Handles ProductsDataSourceDeclarative.Selecting
    ODSEvents.Text = "-- Selecting event fired"
End Sub

Bedenk dat de gebeurtenis van ObjectDataSource Selecting alleen wordt geactiveerd wanneer gegevens worden opgehaald van het onderliggende object. Als de ObjectDataSource toegang heeft tot de gegevens uit de eigen cache, wordt deze gebeurtenis niet geactiveerd.

Bezoek nu deze pagina via een browser. Aangezien we nog geen caching hebben geïmplementeerd, moet elke keer dat u het raster paginat, sorteert of bewerkt, de pagina de tekst 'Selecting event fired' weergeven, zoals Figuur 8 laat zien.

De gebeurtenis Selecteren van de ObjectDataSource wordt geactiveerd telkens wanneer de GridView wordt gepaged, bewerkt of gesorteerd

Afbeelding 8: De gebeurtenis van Selecting de ObjectDataSource wordt geactiveerd telkens wanneer de GridView wordt gepaged, bewerkt of gesorteerd (klik om de afbeelding op volledige grootte weer te geven)

Zoals we hebben gezien in de zelfstudie Caching Data met de ObjectDataSource , zorgt het instellen van de EnableCaching eigenschap ervoor True dat de ObjectDataSource zijn gegevens in de cache opslaat voor de duur die is opgegeven door de CacheDuration eigenschap. De ObjectDataSource heeft ook een SqlCacheDependency eigenschap die een of meer SQL-cache-afhankelijkheden toevoegt aan de gegevens in de cache met behulp van het patroon:

databaseName1:tableName1;databaseName2:tableName2;...

Waarbij databaseName de naam van de database is zoals opgegeven in het name kenmerk van het <add> element in Web.config, en tableName de naam van de databasetabel is. Als u bijvoorbeeld een ObjectDataSource wilt maken die gegevens voor onbepaalde tijd in de cache opslaat op basis van een SQL-cacheafhankelijkheid op basis van de tabel Northwind Products , stelt u de eigenschap ObjectDataSource in EnableCaching op True en de SqlCacheDependency eigenschap op NorthwindDB:Products .

Opmerking

U kunt een SQL-cacheafhankelijkheid en een op tijd gebaseerde vervaldatum gebruiken door in te stellen EnableCaching op True, CacheDuration op het tijdsinterval en SqlCacheDependency op de database- en tabelnaam/-namen. De ObjectDataSource zal zijn gegevens verwijderen wanneer de op tijd gebaseerde vervaldatum is bereikt of wanneer het stemsysteem opmerkt dat de onderliggende databasegegevens zijn gewijzigd, afhankelijk van wat zich het eerst voordoet.

De GridView in SqlCacheDependencies.aspx geeft gegevens weer uit twee tabellen - Products en Categories (het veld 'het product s CategoryName ' wordt opgehaald via een JOIN aan Categories). Daarom willen we twee SQL-cache-afhankelijkheden specificeren: NorthwindDB:Products; NorthwindDB:Categorieën .

De ObjectDataSource configureren ter ondersteuning van caching met behulp van SQL Cache-afhankelijkheden van producten en categorieën

Afbeelding 9: Configureer de ObjectDataSource ter ondersteuning van caching met behulp van SQL Cache-afhankelijkheden op Products en Categories (klik om de afbeelding op volledige grootte weer te geven)

Nadat u de ObjectDataSource hebt geconfigureerd om caching te ondersteunen, bezoekt u de pagina opnieuw via een browser. Nogmaals, de tekst 'Gebeurtenis selecteren die is geactiveerd, moet worden weergegeven bij het eerste paginabezoek, maar moet verdwijnen wanneer u bladert, sorteert of op de knoppen Bewerken of Annuleren klikt. Dit komt omdat nadat de gegevens in de cache van de ObjectDataSource zijn geladen, deze daar blijven totdat de Products of-tabellen Categories worden gewijzigd of de gegevens worden bijgewerkt via de GridView.

Nadat u door het raster hebt gebladerd en het ontbreken van de 'Door gebeurtenis geactiveerde tekst selecteren' hebt opgemerkt, opent u een nieuw browservenster en navigeert u naar de basiszelfstudie in de sectie Bewerken, Invoegen en Verwijderen (~/EditInsertDelete/Basics.aspx). Update de naam of prijs van een product. Bekijk vervolgens in het eerste browservenster een andere pagina met gegevens, sorteer het raster of klik op een rij s Bewerken knop. Deze keer zou de gebeurtenis 'Selecting event fired opnieuw moeten verschijnen, omdat de onderliggende databasegegevens zijn gewijzigd (zie Figuur 10). Als de tekst niet verschijnt, wacht u even en probeert u het opnieuw. Houd er rekening mee dat de pollingservice elke Products milliseconde controleert op wijzigingen in de pollTime tabel, dus er is een vertraging tussen het moment waarop de onderliggende gegevens worden bijgewerkt en het moment waarop de gegevens in de cache worden verwijderd.

Als u de tabel Producten wijzigt, worden de productgegevens in de cache verwijderd

Afbeelding 10: Als u de tabel met producten wijzigt, worden de productgegevens in de cache weergegeven (klik om de afbeelding op volledige grootte te bekijken)

Stap 6: Programmatisch werken met deSqlCacheDependencyklas

In de zelfstudie Caching Data in de Architecture werd gekeken naar de voordelen van het gebruik van een afzonderlijke cachinglaag in de architectuur in plaats van het nauw koppelen van de caching aan de ObjectDataSource. In die tutorial hebben we een ProductsCL class gemaakt om programmatisch werken met de datacache te demonstreren. Als u SQL-cacheafhankelijkheden in de cachinglaag wilt gebruiken, gebruikt u de SqlCacheDependency klasse.

Bij het pollingsysteem moet een SqlCacheDependency object worden gekoppeld aan een bepaald database- en tabelpaar. Met de volgende code wordt bijvoorbeeld een SqlCacheDependency object gemaakt op basis van de tabel van Products de Noordenwind-database:

Dim productsTableDependency As _
    New Caching.SqlCacheDependency("NorthwindDB", "Products")

De twee invoerparameters voor de SqlCacheDependency s-constructor zijn respectievelijk de database- en tabelnamen. Net als bij de eigenschap ObjectDataSource is SqlCacheDependency de gebruikte databasenaam hetzelfde als de waarde die is opgegeven in het name attribuut van het <add> element in Web.config. De tabelnaam is de werkelijke naam van de databasetabel.

Als u a SqlCacheDependency wilt koppelen aan een item dat aan de gegevenscache is toegevoegd, gebruikt u een van de Insert methoden overbelasting die een afhankelijkheid accepteert. De volgende code voegt waarde toe aan de gegevenscache voor onbepaalde tijd, maar koppelt deze aan een SqlCacheDependency op de Products tafel. Kortom, de waarde blijft in de cache totdat deze wordt verwijderd vanwege geheugenbeperkingen of omdat het polling-systeem heeft gedetecteerd dat de tabel is gewijzigd sinds deze in de Products cache is opgeslagen.

Dim productsTableDependency As _
    New Caching.SqlCacheDependency("NorthwindDB", "Products")
Cache.Insert(key, _
             value, _ 
             productsTableDependency, _
             System.Web.Caching.Cache.NoAbsoluteExpiration, _
             System.Web.Caching.Cache.NoSlidingExpiration)

De klasse Caching Layer s ProductsCL slaat momenteel gegevens uit de Products tabel op met een op tijd gebaseerde vervaldatum van 60 seconden. Laten we deze klasse bijwerken zodat deze in plaats daarvan SQL-cache-afhankelijkheden gebruikt. De ProductsCL class s-methode AddCacheItem , die verantwoordelijk is voor het toevoegen van de gegevens aan de cache, bevat momenteel de volgende 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

Werk deze code bij om een SqlCacheDependency object te gebruiken in plaats van de MasterCacheKeyArray cacheafhankelijkheid:

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

Als u deze functionaliteit wilt testen, voegt u een GridView toe aan de pagina onder de bestaande ProductsDeclarative GridView. Stel deze nieuwe GridView-s in ID op ProductsProgrammatic en bind deze via de infotag aan een nieuwe ObjectDataSource met de naam ProductsDataSourceProgrammatic. Configureer de ObjectDataSource voor het gebruik van de ProductsCL klasse en stel de vervolgkeuzelijsten op de tabbladen SELECT en UPDATE in op GetProducts respectievelijk en UpdateProduct.

Configureer de ObjectDataSource voor het gebruik van de klasse ProductsCL

Afbeelding 11: De ObjectDataSource configureren om de ProductsCL klasse te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

Selecteer de GetProducts-methode in de lijst met Drop-Down van het tabblad SELECT

Afbeelding 12: Selecteer de GetProducts methode in de lijst met Drop-Down van het tabblad SELECT (klik om de afbeelding op volledige grootte weer te geven)

Kies de UpdateProduct-methode uit de lijst met Drop-Down van het tabblad UPDATE

Afbeelding 13: Kies de UpdateProduct-methode uit de lijst met Drop-Down van het tabblad UPDATE (klik om de afbeelding op volledige grootte te bekijken)

Na het voltooien van de wizard Gegevensbron configureren, maakt Visual Studio BoundFields en CheckBoxFields in de GridView voor elk van de gegevensvelden. Net als bij de eerste GridView die aan deze pagina is toegevoegd, verwijdert u alle velden behalve ProductName, CategoryName, en UnitPrice, en formatteert u deze velden naar eigen inzicht. Schakel in de infocode van GridView de selectievakjes Paging inschakelen, Sorteren inschakelen en Bewerken inschakelen in. Net als bij de ProductsDataSourceDeclarative ObjectDataSource stelt Visual Studio de eigenschap van ObjectDataSource ProductsDataSourceProgrammatic in OldValuesParameterFormatString op original_{0}. Om ervoor te zorgen dat de bewerkfunctie van GridView goed werkt, stelt u deze eigenschap terug naar {0} (of verwijdert u de eigenschapstoewijzing helemaal uit de declaratieve syntaxis).

Na het voltooien van deze taken moet de resulterende declaratieve opmaak van GridView en ObjectDataSource er als volgt uitzien:

<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>

Als u de SQL-cacheafhankelijkheid in de cachinglaag wilt testen, stelt u een breekpunt in de methode van de ProductCL klasse s AddCacheItem in en begint u met debuggen. Wanneer u het eerst bezoekt SqlCacheDependencies.aspx, moet het breekpunt worden bereikt wanneer de gegevens voor de eerste keer worden opgevraagd en in de cache worden geplaatst. Ga vervolgens naar een andere pagina in de GridView of sorteer een van de kolommen. Dit zorgt ervoor dat de GridView zijn gegevens opnieuw opvraagt, maar de gegevens moeten in de cache worden gevonden omdat de Products databasetabel niet is gewijzigd. Als de gegevens herhaaldelijk niet in de cache worden gevonden, controleert u of er voldoende geheugen op uw computer beschikbaar is en probeert u het opnieuw.

Nadat u een paar pagina's van de GridView hebt doorzocht, opent u een tweede browservenster en navigeert u naar de zelfstudie Basisprincipes in de sectie Bewerken, invoegen en verwijderen (~/EditInsertDelete/Basics.aspx). Werk een record bij vanuit de tabel Producten en bekijk vervolgens vanuit het eerste browservenster een nieuwe pagina of klik op een van de sorteerkoppen.

In dit scenario ziet u een van de volgende twee dingen: ofwel wordt het breekpunt bereikt, wat aangeeft dat de gegevens in de cache zijn verwijderd vanwege de wijziging in de database; Of het breekpunt wordt niet bereikt, wat betekent dat er SqlCacheDependencies.aspx nu verouderde gegevens worden weergegeven. Als het breekpunt niet wordt bereikt, komt dit waarschijnlijk omdat de stembureau nog niet heeft geschoten sinds de gegevens zijn gewijzigd. Houd er rekening mee dat de pollingservice elke Products milliseconde controleert op wijzigingen in de pollTime tabel, dus er is een vertraging tussen het moment waarop de onderliggende gegevens worden bijgewerkt en het moment waarop de gegevens in de cache worden verwijderd.

Opmerking

De kans is groter dat deze vertraging optreedt wanneer u een van de producten bewerkt via de GridView in SqlCacheDependencies.aspx. In de tutorial Caching Data in de Architecture hebben we de MasterCacheKeyArray cacheafhankelijkheid toegevoegd om ervoor te zorgen dat de gegevens die via de ProductsCL class s-methode UpdateProduct worden bewerkt, uit de cache worden verwijderd. We hebben deze cacheafhankelijkheid echter vervangen bij het wijzigen van de AddCacheItem methode eerder in deze stap en daarom zal de klasse de gegevens in de ProductsCL cache blijven weergeven totdat het pollingsysteem de wijziging in de Products tabel opmerkt. In stap 7 zullen we zien hoe we de MasterCacheKeyArray cacheafhankelijkheid opnieuw kunnen introduceren.

Stap 7: Meerdere afhankelijkheden koppelen aan een item in de cache

Bedenk dat de MasterCacheKeyArray cacheafhankelijkheid wordt gebruikt om ervoor te zorgen dat alle productgerelateerde gegevens uit de cache worden verwijderd wanneer een afzonderlijk item dat erin is gekoppeld, wordt bijgewerkt. De GetProductsByCategoryID(categoryID) methode slaat bijvoorbeeld exemplaren op ProductsDataTables voor elke unieke categorie-id-waarde . Als een van deze objecten wordt verwijderd, zorgt de MasterCacheKeyArray cacheafhankelijkheid ervoor dat de andere ook worden verwijderd. Zonder deze cacheafhankelijkheid bestaat de mogelijkheid dat andere productgegevens in de cache verouderd zijn wanneer de gegevens in de cache worden gewijzigd. Daarom is het belangrijk dat we de cacheafhankelijkheid behouden bij het MasterCacheKeyArray gebruik van SQL-cacheafhankelijkheden. De methode van Insert de gegevenscache staat echter slechts één afhankelijkheidsobject toe.

Bovendien moeten we bij het werken met SQL-cache-afhankelijkheden mogelijk meerdere databasetabellen als afhankelijkheden koppelen. De ProductsDataTable cache in de ProductsCL klasse bevat bijvoorbeeld de categorie- en leveranciersnamen voor elk product, maar de AddCacheItem methode gebruikt alleen een afhankelijkheid van Products. Als de gebruiker in dit geval de naam van een categorie of leverancier bijwerkt, blijven de productgegevens in de cache staan en zijn ze verouderd. Daarom willen we de productdata in de cache niet alleen afhankelijk maken van de Products tabel, maar ook van de Categories en Suppliers tabellen.

De AggregateCacheDependency klasse biedt een manier om meerdere afhankelijkheden te koppelen aan een cache-item. Begin met het maken van een AggregateCacheDependency exemplaar. Voeg vervolgens de set afhankelijkheden toe met behulp van de AggregateCacheDependencyAdd s-methode. Wanneer u het item daarna in de gegevenscache invoegt, geeft u de AggregateCacheDependency instantie door. Wanneer een van de afhankelijkheden van de AggregateCacheDependency instantie wordt gewijzigd, wordt het item in de cache verwijderd.

Hieronder ziet u de bijgewerkte code voor de ProductsCL methode klasse s AddCacheItem . Met deze methode wordt de MasterCacheKeyArray cache-afhankelijkheid gemaakt, samen met SqlCacheDependency objecten voor de Products, Categories, en Suppliers tabellen. Deze worden allemaal gecombineerd tot één AggregateCacheDependency object met de naam aggregateDependencies, dat vervolgens wordt doorgegeven aan de Insert methode.

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

Test deze nieuwe code uit. Wijzigingen in de Products, Categories, of Suppliers tabellen zorgen er nu voor dat de gegevens in de cache worden verwijderd. Bovendien elimineert de ProductsCL class s-methode UpdateProduct , die wordt aangeroepen bij het bewerken van een product via de GridView, de MasterCacheKeyArray cache-afhankelijkheid, waardoor de cache ProductsDataTable wordt verwijderd en de gegevens bij het volgende verzoek opnieuw worden opgehaald.

Opmerking

SQL-cacheafhankelijkheden kunnen ook worden gebruikt met uitvoercaching. Zie voor een demonstratie van deze functionaliteit: ASP.NET Output Caching gebruiken met SQL Server.

Samenvatting

Bij het cachen van databasegegevens blijven de gegevens idealiter in de cache totdat ze in de database worden gewijzigd. Met ASP.NET 2.0 kunnen SQL-cacheafhankelijkheden worden gemaakt en gebruikt in zowel declaratieve als programmatische scenario's. Een van de uitdagingen bij deze aanpak is om te ontdekken wanneer de gegevens zijn gewijzigd. De volledige versies van Microsoft SQL Server 2005 bieden meldingsmogelijkheden waarmee een toepassing kan worden gewaarschuwd wanneer het resultaat van een query is gewijzigd. Voor de Express-editie van SQL Server 2005 en oudere versies van SQL Server moet in plaats daarvan een pollingsysteem worden gebruikt. Gelukkig is het opzetten van de benodigde stembureau-infrastructuur vrij eenvoudig.

Veel plezier met programmeren!

Meer lezen

Raadpleeg de volgende bronnen voor meer informatie over de onderwerpen die in deze zelfstudie worden besproken:

Over de auteur

Scott Mitchell, auteur van zeven ASP/ASP.NET-boeken en oprichter van 4GuysFromRolla.com, werkt sinds 1998 met Microsoft-webtechnologieën. Scott werkt als onafhankelijk consultant, trainer en schrijver. Zijn laatste boek is Sams Teach Yourself ASP.NET 2.0 in 24 uur. Hij kan worden bereikt op mitchell@4GuysFromRolla.com.

Speciale dank aan

Deze tutorialreeks is beoordeeld door veel behulpzame beoordelers. Hoofdbeoordelaars voor deze tutorial waren Marko Rangel, Teresa Murphy en Hilton Giesenow. Bent u geïnteresseerd in het bekijken van mijn aanstaande MSDN-artikelen? Zo ja, laat iets van je horen via mitchell@4GuysFromRolla.com.