Megosztás a következőn keresztül:


SQL Cache-függőségek használata (C#)

által Scott Mitchell

PDF letöltése

A legegyszerűbb gyorsítótárazási stratégia az, hogy a gyorsítótárazott adatok meghatározott idő elteltével lejárjanak. Ez az egyszerű megközelítés azonban azt jelenti, hogy a gyorsítótárazott adatok nem társíthatók a mögöttes adatforrással, ami elavult adatokat eredményez, amelyek túl hosszúak, vagy a jelenlegi adatok túl hamar lejárnak. Jobb megközelítés az SqlCacheDependency osztály használata, hogy az adatok gyorsítótárazva maradjanak, amíg a mögöttes adatok módosulnak az SQL-adatbázisban. Ez az oktatóanyag bemutatja, hogyan.

Bevezetés

A Gyorsítótár-módszerek az ObjectDataSource használatával és az architektúrában történő adatgyorsítás című oktatóanyagokban vizsgált technikák időalapú lejárati időt alkalmaztak, hogy meghatározott időszak után kiürítsék az adatokat a gyorsítótárból. Ez a módszer a legegyszerűbb módja annak, hogy kiegyensúlyozza a gyorsítótárazás teljesítménynövekedését az adatok elavultságával szemben. Ha x másodperces időkorlátot választ, az oldal fejlesztője elismeri, hogy csak x másodpercig élvezheti a gyorsítótárazás előnyeit, de megnyugodhat, hogy adatai legfeljebb x másodpercig maradnak frissek. A statikus adatok esetében az x természetesen kiterjeszthető a webalkalmazás teljes élettartamára, ahogyan az az Alkalmazásindításkor végzett adatok gyorsítótárazása című oktatóanyagban tárgyaltuk.

Adatbázisadatok gyorsítótárazásakor gyakran az időalapú lejáratot választják a könnyű használat érdekében, de gyakran nem megfelelő megoldás. Ideális esetben az adatbázis adatai gyorsítótárazva maradnak, amíg az alapul szolgáló adatokat nem módosítják az adatbázisban; csak akkor kell kiüríteni a gyorsítótárat. Ez a megközelítés maximalizálja a gyorsítótárazás teljesítménybeli előnyeit, és minimálisra csökkenti az elavult adatok időtartamát. Ahhoz azonban, hogy élvezhesse ezeket az előnyöket, léteznie kell egy olyan rendszernek, amely tudja, mikor módosultak a mögöttes adatbázis adatai, és kizárja a megfelelő elemeket a gyorsítótárból. A 2.0-s ASP.NET előtt a lapfejlesztők tették lehetővé a rendszer implementálását.

ASP.NET 2.0 egy SqlCacheDependency osztályt és a szükséges infrastruktúrát biztosít annak meghatározásához, hogy mikor történt változás az adatbázisban a megfelelő gyorsítótárazott elemek kiürítéséhez. A mögöttes adatok módosításának két módszere van: az értesítés és a lekérdezés. Az értesítés és a lekérdezés közötti különbségek megvitatása után létrehozzuk a lekérdezés támogatásához szükséges infrastruktúrát, majd megismerjük, hogyan használhatja az SqlCacheDependency osztályt deklaratív és programozott forgatókönyvekben.

Az értesítés és a lekérdezés ismertetése

Az adatbázis adatainak módosításának két módszere használható: az értesítés és a lekérdezés. Értesítés esetén az adatbázis automatikusan riasztást küld a ASP.NET futtatókörnyezetről, amikor egy adott lekérdezés eredményei módosultak a lekérdezés legutóbbi végrehajtása óta, és ekkor a rendszer kizárja a lekérdezéshez társított gyorsítótárazott elemeket. A lekérdezéssel az adatbázis-kiszolgáló megőrzi az adott táblák legutóbbi frissítésének időpontjára vonatkozó információkat. A ASP.NET futtatókörnyezet rendszeres időközönként lekérdezi az adatbázist, hogy ellenőrizze, mely táblák változtak a gyorsítótárba való beírásuk óta. Azok a táblák, amelyek adatai módosultak, kiürítették a társított gyorsítótárelemeket.

Az értesítési beállítás kevesebb beállítást igényel, mint a lekérdezés, és részletesebb, mivel nem a tábla szintjén, hanem a lekérdezés szintjén követi nyomon a változásokat. Sajnos az értesítések csak a Microsoft SQL Server 2005 teljes kiadásaiban érhetők el (azaz a nem Express kiadásokban). A lekérdezési lehetőség azonban a Microsoft SQL Server 7.0 és 2005 közötti összes verziójához használható. Mivel ezek az oktatóanyagok az SQL Server 2005 Express kiadását használják, a lekérdezési lehetőség beállítására és használatára összpontosítunk. Az SQL Server 2005 értesítési képességeivel kapcsolatos további forrásokért tekintse meg az oktatóanyag végén található További olvasás című szakaszt.

Kérdezéses lekérdezés esetén az adatbázist úgy kell konfigurálni, hogy tartalmazzon egy AspNet_SqlCacheTablesForChangeNotification táblát, amely három oszlopot tartalmaz – tableName, notificationCreated és changeId. Ez a táblázat minden olyan táblához tartalmaz egy sort, amely olyan adatokat tartalmaz, amelyeket esetleg a webalkalmazás SQL Cache-függőségében kell használni. Az tableName oszlop megadja a tábla nevét, és notificationCreated jelzi a sor táblához való hozzáadásának dátumát és időpontját. Az changeId oszlop típusa int 0, kezdeti értéke 0. Az érték a tábla minden módosításával növekszik.

A táblán kívül az AspNet_SqlCacheTablesForChangeNotification adatbázisnak is tartalmaznia kell eseményindítókat az SQL Cache-függőségben esetlegesen megjelenő táblákon. Ezek az eseményindítók akkor lesznek végrehajtva, amikor egy sort beszúrnak, frissítenek vagy törölnek, és növelik a tábla s changeId értékét a fájlban AspNet_SqlCacheTablesForChangeNotification.

Az ASP.NET futtatókörnyezet nyomon követi a jelenlegi changeId-t egy táblához, amikor adatokat gyorsítótárazunk egy SqlCacheDependency objektummal. A rendszer rendszeresen ellenőrzi az adatbázist, és minden olyan SqlCacheDependency objektumot kizár, amelynek changeId értéke eltér az adatbázisban megadott értéktől, mivel az eltérő changeId érték azt jelzi, hogy a táblában változás történt az adatok gyorsítótárazása óta.

1. lépés: A parancssoriaspnet_regsql.exeprogram felfedezése

A lekérdezési megközelítéssel az adatbázist úgy kell beállítani, hogy tartalmazza a fent leírt infrastruktúrát: egy előre definiált táblát (AspNet_SqlCacheTablesForChangeNotification), egy maroknyi tárolt eljárást és triggereket az egyes táblákon, amelyek a webalkalmazás SQL Cache-függőségeiben használhatók. Ezek a táblák, tárolt eljárások és eseményindítók a mappában aspnet_regsql.exe található parancssori programon $WINDOWS$\Microsoft.NET\Framework\versionkeresztül hozhatók létre. A tábla és a AspNet_SqlCacheTablesForChangeNotification társított tárolt eljárások létrehozásához futtassa a következőt a parancssorból:

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

Megjegyzés:

A parancsok végrehajtásához a megadott adatbázis-bejelentkezésnek az db_securityadmin és db_ddladmin szerepkörökben kell lennie.

Ha például egy Windows-hitelesítést használó adatbázis-kiszolgálón elnevezett pubsScottsServer Microsoft SQL Server-adatbázishoz szeretné hozzáadni a lekérdezési infrastruktúrát, keresse meg a megfelelő könyvtárat, és a parancssorból írja be a következőt:

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

Az adatbázisszintű infrastruktúra hozzáadása után hozzá kell adnunk az eseményindítókat az SQL Cache-függőségekben használt táblákhoz. Ismét használja a aspnet_regsql.exe parancssori programot, de adja meg a tábla nevét a -t kapcsolóval, és ahelyett, hogy a -ed kapcsolót használná, használja a -et kapcsolót, így:

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

Ha hozzá szeretné adni az eseményindítókat az authors adatbázis titles és pubs tábláihoz ScottsServer használja a következőt:

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

Ebben az oktatóanyagban adja hozzá az eseményindítókat a Products, Categories és Suppliers táblákhoz. A 3. lépésben áttekintjük a parancssor adott szintaxisát.

2. lépés: Microsoft SQL Server 2005 Express Edition-adatbázisra való hivatkozásApp_Data

A aspnet_regsql.exe parancssori programnak szüksége van az adatbázisra és a kiszolgáló nevére a szükséges lekérdezési infrastruktúra hozzáadásához. De mi a mappában App_Data található Microsoft SQL Server 2005 Express-adatbázis adatbázisa és kiszolgálóneve? Ahelyett, hogy felderítenék az adatbázis és a kiszolgáló nevét, azt találtam, hogy a legegyszerűbb módszer az adatbázis csatolása az localhost\SQLExpress adatbázis-példányhoz, és átnevezni az adatokat az SQL Server Management Studio használatával. Ha az SQL Server 2005 egyik teljes verziója telepítve van a számítógépen, akkor valószínűleg már telepítve van az SQL Server Management Studio a számítógépre. Ha csak az Express kiadással rendelkezik, letöltheti az ingyenes Microsoft SQL Server Management Studio Express Editiont.

Először zárja be a Visual Studio-t. Ezután nyissa meg az SQL Server Management Studiót, és válassza a kiszolgálóhoz való csatlakozást a localhost\SQLExpress Windows-hitelesítés használatával.

Csatolás a localhost\SQLExpress Serverhez

1. ábra: Csatolás a localhost\SQLExpress kiszolgálóhoz

A kiszolgálóhoz való csatlakozás után a Management Studio megjeleníti a kiszolgálót, és almappákkal rendelkezik az adatbázisokhoz, a biztonsághoz és így tovább. Kattintson a jobb gombbal az Adatbázisok mappára, és válassza a Csatolás lehetőséget. Ekkor megjelenik az Adatbázisok csatolása párbeszédpanel (lásd a 2. ábrát). Kattintson a Hozzáadás gombra, és válassza ki az NORTHWND.MDF adatbázismappát a webalkalmazás mappájában App_Data .

Csatlakoztassa a NORTHWND.MDF adatbázist az App_Data mappából

2. ábra: Az adatbázis csatolása NORTHWND.MDF a App_Data mappából (kattintson ide a teljes méretű kép megtekintéséhez)

Ezzel hozzáadja az adatbázist az Adatbázisok mappához. Az adatbázis neve lehet az adatbázisfájl teljes elérési útja, vagy a GUID-dal az elején kiegészített teljes elérési út. Ha el szeretné kerülni, hogy a aspnet_regsql.exe parancssori eszköz használatakor ne kelljen beírnia ezt a hosszú adatbázisnevet, nevezze át az adatbázist emberbarátabb névre úgy, hogy a jobb gombbal az imént csatolt adatbázisra kattint, és az Átnevezés parancsot választja. Átneveztem az adatbázisomat DataTutorials névre.

A csatolt adatbázis átnevezése további Human-Friendly névre

3. ábra: A csatolt adatbázis átnevezése további Human-Friendly névre

3. lépés: A lekérdezési infrastruktúra hozzáadása a Northwind-adatbázishoz

Most, hogy csatoltuk az NORTHWND.MDF adatbázist a App_Data mappából, készen állunk a lekérdezési infrastruktúra hozzáadására. Tegyük fel, hogy átnevezte az adatbázist DataTutorials névre, futtassa a következő négy parancsot:

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

A négy parancs futtatása után kattintson a jobb gombbal az adatbázis nevére a Management Studióban, nyissa meg a Feladatok almenüt, és válassza a Leválasztás lehetőséget. Ezután zárja be a Management Studiót, és nyissa meg újra a Visual Studiót.

Miután a Visual Studio újra megnyílt, a Kiszolgálókezelőn keresztül részletezheti az adatbázist. Figyelje meg az új táblát (AspNet_SqlCacheTablesForChangeNotification), az új tárolt eljárásokat, valamint a Products, Categories és Suppliers táblák triggereit.

Az adatbázis most már tartalmazza a szükséges lekérdezési infrastruktúrát

4. ábra: Az adatbázis most már tartalmazza a szükséges lekérdezési infrastruktúrát

4. lépés: A lekérdezési szolgáltatás konfigurálása

Miután létrehozta a szükséges táblákat, eseményindítókat és tárolt eljárásokat az adatbázisban, az utolsó lépés a lekérdezési szolgáltatás konfigurálása, amely a használni kívánt adatbázisok és a lekérdezési gyakoriság ezredmásodpercben történő megadásával történik Web.config . Az alábbi korrektúra másodpercenként egyszer kérdezi le a Northwind-adatbázist.

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

Az name elem ( <add> NorthwindDB) értéke egy ember által olvasható nevet társít egy adott adatbázishoz. Az SQL Cache-függőségek használatakor az itt definiált adatbázis nevére és a gyorsítótárazott adatok alapjául használt táblára kell hivatkoznunk. A 6. lépésben látni fogjuk, hogyan használhatjuk az SqlCacheDependency osztályt, hogy programozott módon társítsuk az SQL gyorsítótárazási függőségeket a gyorsítótárazott adatokkal.

Miután létrejött egy SQL Cache-függőség, a lekérdezési rendszer minden <databases> ezredmásodpercben csatlakozik az pollTime elemekben meghatározott adatbázisokhoz, és végrehajtja a AspNet_SqlCachePollingStoredProcedure tárolt eljárást. Ez a tárolt eljárás, amelyet a aspnet_regsql.exe parancssori eszközzel adtak hozzá a 3. lépésben, visszaadja az tableName és changeId értékeket minden rekordhoz a AspNet_SqlCacheTablesForChangeNotification-ben. Az elavult SQL Cache-függőségek törlődnek a gyorsítótárból.

A pollTime beállítás kompromisszumot vezet be a teljesítmény és az adatok elavultsága között. Egy kis pollTime érték növeli az adatbázisra irányuló kérések számát, de gyorsabban kiüríti az elavult adatokat a gyorsítótárból. A nagyobb pollTime érték csökkenti az adatbázis-kérelmek számát, de növeli a háttéradatok változása és a kapcsolódó gyorsítótárelemek kizárása közötti késleltetést. Szerencsére az adatbázis-kérelem egy egyszerű tárolt eljárást hajt végre, amely csak néhány sort ad vissza egy egyszerű, egyszerűsített táblából. Kísérletezzen azonban különböző pollTime értékekkel, hogy ideális egyensúlyt találjon az adatbázis-hozzáférés és az adatok elavultsága között az alkalmazás számára. A legkisebb pollTime megengedett érték 500.

Megjegyzés:

A fenti példa egyetlen pollTime értéket biztosít az <sqlCacheDependency> elemben, de igény szerint megadhatja az pollTime<add> elem értékét. Ez akkor hasznos, ha több adatbázis van megadva, és testre szeretné szabni az adatbázisonkénti lekérdezési gyakoriságot.

5. lépés: Az SQL Cache-függőségek deklaratív használata

Az 1–4. lépésben áttekintettük, hogyan állíthatja be a szükséges adatbázis-infrastruktúrát és konfigurálhatja a lekérdezési rendszert. Ezzel az infrastruktúrával most már hozzáadhatunk elemeket a gyorsítótárhoz egy kapcsolódó SQL gyorsítótár-függőséggel, programozott vagy deklaratív módszerek alkalmazásával. Ebben a lépésben azt vizsgáljuk meg, hogyan használható deklaratívan az SQL Cache-függőségekkel. A 6. lépésben a programozott megközelítést vizsgáljuk meg.

Az Adatok gyorsítótárazása az ObjectDataSource oktatóanyaggal az ObjectDataSource deklaratív gyorsítótárazási képességeit vizsgálta. Ha egyszerűen beállítja a EnableCaching tulajdonságot true értékre, és a CacheDuration tulajdonságot egy adott időintervallumra, az ObjectDataSource automatikusan gyorsítótárazza a mögöttes objektumból visszaadott adatokat a megadott időközhöz. Az ObjectDataSource egy vagy több SQL Cache-függőséget is használhat.

Ha deklaratív módon szeretné bemutatni az SQL Cache-függőségek használatát, nyissa meg a SqlCacheDependencies.aspx lapot a Caching mappában, és húzzon egy GridView-t az eszközkészletből a Tervezőbe. Állítsa be a GridView ID-t ProductsDeclarative-re, és az intelligens címkéből válassza ki, hogy egy új ObjectDataSource-hoz kösse, amely a ProductsDataSourceDeclarative nevet kapja.

Új, ProductsDataSourceDeclarative nevű ObjectDataSource létrehozása

5. ábra: Új ObjectDataSource névvel ellátott ProductsDataSourceDeclarative objektum létrehozása (ide kattintva megtekintheti a teljes méretű képet)

Konfigurálja az ObjectDataSource-t az ProductsBLL osztály használatára, és állítsa a SELECT lapon a legördülő listát a következőre GetProducts(): . Az UPDATE lapon válassza ki a UpdateProduct túlterhelést három bemeneti paraméterrel : productName, unitPriceés productID. Állítsa a legördülő listákat (Nincs) értékre az INSERT és a DELETE lapon.

Az UpdateProduct Túlterhelés használata három bemeneti paraméterrel

6. ábra: Az UpdateProduct Túlterhelés használata három bemeneti paraméterrel (kattintson ide a teljes méretű kép megtekintéséhez)

Állítsa be a Drop-Down listát (Nincs) értékre az INSERT és DELETE lapoknál

7. ábra: Állítsa a Drop-Down listát a (Nincs) értékre az INSERT és DELETE fülekhez (kattintson ide a teljes méretű kép megtekintéséhez)

Az Adatforrás konfigurálása varázsló befejezése után a Visual Studio minden adatmezőhöz létrehozza a BoundFields és a CheckBoxFields elemet a GridView-ban. Távolítsa el az összes mezőt, kivéve a ProductName, CategoryName, és UnitPrice; formázza ezeket a mezőket, ahogy szükségesnek látja. A GridView intelligens címkéje alapján jelölje be a Lapozás engedélyezése, a Rendezés engedélyezése és a Szerkesztés engedélyezése jelölőnégyzetet. A Visual Studio az OldValuesParameterFormatString tulajdonságot az ObjectDataSource original_{0} értékre állítja. Ahhoz, hogy a GridView szerkesztési funkciója megfelelően működjön, távolítsa el ezt a tulajdonságot teljesen a deklaratív szintaxisból, vagy állítsa vissza az alapértelmezett értékre. {0}

Végül vegyen fel egy Felirat webvezérlőt a GridView fölé, és állítsa be a ID tulajdonságát ODSEvents-re, valamint a EnableViewState tulajdonságát false-ra. A módosítások elvégzése után a lap deklaratív korrektúrája az alábbihoz hasonlóan fog kinézni. Vegye figyelembe, hogy számos olyan esztétikai testreszabást végeztem a GridView mezőkön, amelyek nem szükségesek az SQL Cache függőségi funkciójának bemutatásához.

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

Ezután hozzon létre egy eseménykezelőt az ObjectDataSource eseményéhez Selecting , és adja hozzá a következő kódot:

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

Ne feledje, hogy az ObjectDataSource eseménye csak akkor aktiválódik Selecting , ha adatokat hív le a mögöttes objektumból. Ha az ObjectDataSource a saját gyorsítótárából fér hozzá az adatokhoz, a rendszer nem aktiválja ezt az eseményt.

Most látogasson el erre a lapra egy böngészőben. Mivel még nem valósítottunk meg gyorsítótárazást, a rács minden egyes lapozásakor, rendezésekor vagy szerkesztésekor a "Kiválasztási esemény aktiválva" szövegnek kell megjelennie, ahogy a 8. ábra mutatja.

Az ObjectDataSource kiválasztási eseménye minden alkalommal aktiválódik, amikor a GridView lapozott, szerkesztett vagy rendezett

8. ábra: Az ObjectDataSource eseménye minden alkalommal aktiválódik Selecting , amikor a GridView lapozott, szerkesztett vagy rendezett (ide kattintva megtekintheti a teljes méretű képet)

Ahogy az Adatok gyorsítótárazása az ObjectDataSource-szal című oktatóanyagban láttuk, a EnableCaching tulajdonság true értékre állításával az ObjectDataSource gyorsítótárazza az adatokat a CacheDuration tulajdonság által megadott ideig. Az ObjectDataSource rendelkezik egy SqlCacheDependency tulajdonságtal is, amely egy vagy több SQL Cache-függőséget ad hozzá a gyorsítótárazott adatokhoz a minta használatával:

databaseName1:tableName1;databaseName2:tableName2;...

Ahol a databaseName az adatbázis neve a name elem <add> attribútumában megadott módon, a Web.config pedig az adatbázis táblájának neve. Ha például olyan ObjectDataSource-t szeretne létrehozni, amely a Northwind táblához Products tartozó SQL Cache-függőség alapján határozatlan ideig gyorsítótárazza az adatokat, állítsa be az ObjectDataSource EnableCaching tulajdonságát true értékre, és a SqlCacheDependency tulajdonságát a NorthwindDB:Products értékre.

Megjegyzés:

Az SQL Cache-függőséget és az időalapú lejáratot EnableCachingtrueúgy használhatja, hogy az időintervallumot, CacheDurationSqlCacheDependency valamint az adatbázist és a táblanevet állítja be. Az ObjectDataSource kiüríti az adatokat az időalapú lejárat elérésekor, vagy amikor a lekérdezési rendszer megjegyzi, hogy a mögöttes adatbázis adatai megváltoztak, attól függően, hogy melyik történik először.

A SqlCacheDependencies.aspx GridView megjeleníti az adatsorokat két táblából: Products és Categories (a termék CategoryName mezője egy JOIN segítségével a Categories-on érhető el). Ezért két SQL Cache-függőséget szeretnénk megadni: NorthwindDB:Products; NorthwindDB:Categories .

Az ObjectDataSource konfigurálása a gyorsítótárazás támogatásához az SQL Cache termékekre és kategóriákra vonatkozó függőségeivel

9. ábra: Konfigurálja az ObjectDataSource-t az SQL Cache-függőségek használatával a gyorsítótárazás támogatására Products és Categories esetén (Kattintson ide a teljes méretű kép megtekintéséhez)

Miután konfigurálta az ObjectDataSource-t a gyorsítótárazás támogatásához, nyissa meg újra a lapot egy böngészőben. Ismét az "Esemény kiválasztása aktiválva" szövegnek kell megjelennie az első oldallátogatáskor, de a Lapozás, rendezés vagy a Szerkesztés vagy a Mégse gombra való kattintáskor el kell tűnnie. Ennek az az oka, hogy miután az adatok betöltődtek az ObjectDataSource gyorsítótárába, azok mindaddig ott maradnak, amíg a Products vagy Categories táblákat nem módosítják, vagy az adatokat a GridView-on keresztül frissítik.

Miután végiglapozta a rácsot, és megjegyezte az "Esemény kiválasztásának szövege" hiányát, nyisson meg egy új böngésző ablakot, és lépjen az Alapismeretek oktatóanyagra a Szerkesztés, Beszúrás és Törlés szakaszban (~/EditInsertDelete/Basics.aspx). Frissítse a termék nevét vagy árát. Ezután az első böngészőablakban tekintse meg az adatok egy másik oldalát, rendezze a rácsot, vagy kattintson a Sor szerkesztése gombra. Ezúttal ismét megjelenik az "Aktivált esemény kiválasztása" beállítás, mivel a mögöttes adatbázis adatai módosultak (lásd a 10. ábrát). Ha a szöveg nem jelenik meg, várjon néhány percet, és próbálkozzon újra. Ne feledje, hogy a lekérdezési szolgáltatás minden Products ezredmásodpercben ellenőrzi a pollTime tábla módosításait, így a mögöttes adatok frissítése és a gyorsítótárazott adatok kiürítése között késés tapasztalható.

A Termékek tábla módosítása kiüríti a gyorsítótárazott termékadatokat

10. ábra: A Termékek tábla módosítása eltávolítja a gyorsítótárból a termékadatokat (A teljes méretű képet a kattintva tekintheti meg)

6. lépés: Az osztály programozott használataSqlCacheDependency

Az architektúrában történő gyorsítótárazás oktatóanyaga azt vizsgálta, hogy milyen előnyökkel jár egy külön gyorsítótárazási réteg használata az architektúrában ellentétben azzal, hogy szorosan összekapcsoljuk a gyorsítótárazást az ObjectDataSource-zal. Ebben az oktatóanyagban létrehoztunk egy osztályt ProductsCL , amely bemutatja az adatgyorsítótár programozott működését. Az SQL cache-függőségek gyorsítótárazási rétegben való használatának érdekében használja a SqlCacheDependency osztályt.

A lekérdezési rendszerben egy objektumot SqlCacheDependency egy adott adatbázishoz és táblapárhoz kell társítani. A következő kód például létrehoz egy SqlCacheDependency objektumot a Northwind-adatbázis táblája Products alapján:

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

Az SqlCacheDependency s konstruktor két bemeneti paramétere sorrendben az adatbázis és a tábla neve. Az ObjectDataSource SqlCacheDependency tulajdonsághoz hasonlóan a használt adatbázisnév megegyezik a name elem <add> attribútumában Web.config megadott értékkel. A tábla neve az adatbázistábla tényleges neve.

Ha társítani szeretne egy SqlCacheDependency elemet egy adatgyorsítótárhoz hozzáadott elemhez, használja a Insert függőséget elfogadó egyik metódustöbblet. Az alábbi kód határozatlan ideig ad hozzá értéket az adatgyorsítótárhoz, de társítja azt egy SqlCacheDependencyProducts táblához. Röviden: az érték mindaddig a gyorsítótárban marad, amíg a memóriakorlátozások miatt ki nem iktatott, vagy mert a lekérdezési rendszer azt észlelte, hogy a Products tábla a gyorsítótárazás óta megváltozott.

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

A gyorsítótárazási réteg s ProductsCL osztálya jelenleg 60 másodperces időalapú lejárattal gyorsítótárazza az adatokat a Products táblából. Frissítse ezt az osztályt úgy, hogy ehelyett SQL Cache-függőségeket használjon. Az ProductsCL s osztály AddCacheItem metódusa, amely az adatok gyorsítótárba való hozzáadásáért felelős, jelenleg a következő kódot tartalmazza:

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);
}

Frissítse ezt a kódot úgy, hogy a gyorsítótár-függőség helyett egy SqlCacheDependencyMasterCacheKeyArray objektumot használjon:

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);
}

A funkció teszteléséhez vegyen fel egy GridView-t a meglévő ProductsDeclarative GridView alatti lapra. Állítsa be az új GridView-t IDProductsProgrammatic, és az intelligens címkéjén keresztül kösse össze egy új, ObjectDataSource nevű ProductsDataSourceProgrammatic objektummal. Konfigurálja az ObjectDataSource-t az ProductsCL osztály használatára, és állítsa be a SELECT fül legördülő listáját az GetProducts, valamint az UPDATE fül legördülő listáját az UpdateProduct értékére.

Az ObjectDataSource konfigurálása a ProductsCL-osztály használatára

11. ábra: Az ObjectDataSource konfigurálása az ProductsCL osztály használatára (kattintson ide a teljes méretű kép megtekintéséhez)

Válassza ki a GetProducts metódust a SELECT tab Drop-Down listából

12. ábra: Válassza ki a metódust a GetProducts SELECT tab Drop-Down listából (kattintson ide a teljes méretű kép megtekintéséhez)

Válassza ki az UpdateProduct metódust az UPDATE lap Drop-Down listájából

13. ábra: Válassza ki az UpdateProduct metódust az UPDATE lap Drop-Down listájából (kattintson ide a teljes méretű kép megtekintéséhez)

Az Adatforrás konfigurálása varázsló befejezése után a Visual Studio minden adatmezőhöz létrehozza a BoundFields és a CheckBoxFields elemet a GridView-ban. A laphoz hozzáadott első GridView-hoz hasonlóan távolítsa el az összes mezőt, kivéve ProductName, CategoryName, és UnitPrice, és formázza ezeket a mezőket úgy, ahogy látja jónak. A GridView intelligens címkéje alapján jelölje be a Lapozás engedélyezése, a Rendezés engedélyezése és a Szerkesztés engedélyezése jelölőnégyzetet. Visual Studio az ObjectDataSource-hoz hasonlóan beállítja az ObjectDataSource ProductsDataSourceDeclarative tulajdonságát ProductsDataSourceProgrammatic. Ahhoz, hogy a GridView szerkesztési funkciója megfelelően működjön, állítsa vissza {0} ezt a tulajdonságot (vagy távolítsa el a tulajdonság-hozzárendelést a deklaratív szintaxisból).

A feladatok elvégzése után az eredményként kapott GridView és ObjectDataSource deklaratív korrektúra a következőképpen néz ki:

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

Az SQL Cache függőségének a gyorsítótárazási rétegben való teszteléséhez állítson be egy töréspontot az ProductCL s AddCacheItem osztály metódusában, majd kezdje el a hibakeresést. Az első látogatáskor a SqlCacheDependencies.aspx töréspontot el kell érni, mivel az adatokat először kérik le, és helyezik el a gyorsítótárba. Ezután lépjen egy másik lapra a GridView-ban, vagy rendezze az egyik oszlopot. Ez azt eredményezi, hogy a GridView újra lekérdezi az adatokat, de az adatokat a gyorsítótárban kell megtalálni, mivel az Products adatbázistáblát nem módosították. Ha az adatok ismételten nem találhatók a gyorsítótárban, győződjön meg arról, hogy elegendő memória áll rendelkezésre a számítógépen, és próbálkozzon újra.

A GridView néhány oldalának lapozása után nyisson meg egy második böngészőablakot, és keresse meg az Alapismeretek oktatóanyagot a Szerkesztés, beszúrás és törlés szakaszban (~/EditInsertDelete/Basics.aspx). Frissítsen egy rekordot a Termékek táblából, majd az első böngészőablakban tekintse meg az új lapot, vagy kattintson az egyik rendezési fejlécre.

Ebben a forgatókönyvben két dolog egyikét fogja látni: a töréspontot a rendszer eléri, ami azt jelzi, hogy a gyorsítótárazott adatokat a rendszer törölte az adatbázis változása miatt; vagy a töréspontot nem éri el a rendszer, ami azt jelenti, hogy SqlCacheDependencies.aspx most régi adatokat jelenít meg. Ha a töréspontot nem éri el a rendszer, valószínűleg az az oka, hogy a lekérdezési szolgáltatás még nem aktiválódott az adatok módosítása óta. Ne feledje, hogy a lekérdezési szolgáltatás minden Products ezredmásodpercben ellenőrzi a pollTime tábla módosításait, így a mögöttes adatok frissítése és a gyorsítótárazott adatok kiürítése között késés tapasztalható.

Megjegyzés:

Ez a késés nagyobb valószínűséggel jelenik meg, amikor az egyik terméket a GridView-on keresztül szerkeszti.SqlCacheDependencies.aspx Az Adatok gyorsítótárazása az architektúrában című oktatóanyagban hozzáadtuk a MasterCacheKeyArray gyorsítótár-függőséget, hogy az ProductsCL osztály UpdateProduct metódusával szerkesztett adatokat eltávolítsuk a gyorsítótárból. Ezt a gyorsítótár-függőséget azonban lecseréltük a AddCacheItem módszer ezen lépés korábbi módosításakor, ezért az ProductsCL osztály továbbra is megjeleníti a gyorsítótárazott adatokat, amíg a lekérdezési rendszer nem veszi figyelembe a Products tábla módosítását. A 7. lépésben látni fogjuk, hogyan lehet újra bevezetni a MasterCacheKeyArray gyorsítótár-függőséget.

7. lépés: Több függőség társítása gyorsítótárazott elemhez

Ne feledje, hogy a MasterCacheKeyArray gyorsítótár-függőség használatával biztosítható, hogy a termékhez kapcsolódó összes adat törlődjön a gyorsítótárból, amikor a hozzá társított elemek frissülnek. Például, a GetProductsByCategoryID(categoryID) metódus a minden egyes egyedi ProductsDataTables tartozó példányokat gyorsítótárazza. Ha az egyik objektumot kiüríti, a MasterCacheKeyArray gyorsítótár-függőség biztosítja, hogy a többi is törlődjön. A gyorsítótár-függőség nélkül, a gyorsítótárazott adatok módosításakor fennáll annak a lehetősége, hogy a gyorsítótárazott termékadatok elavultak lehetnek. Ezért fontos, hogy az SQL Cache-függőségek használatakor fenntartsuk a MasterCacheKeyArray gyorsítótár-függőséget. Az adatgyorsítótár metódusa Insert azonban csak egyetlen függőségi objektumot engedélyez.

Emellett az SQL Cache-függőségek használatakor előfordulhat, hogy több adatbázistáblát kell függőségként társítanunk. ProductsDataTable a gyorsítótár az osztályban tartalmazza a termékek kategória- és szállítóneveit, de a ProductsCL metódus csak AddCacheItem függőséget használ. Ebben az esetben, ha a felhasználó frissíti egy kategória vagy szállító nevét, a gyorsítótárazott termékadatok a gyorsítótárban maradnak, és elavultak lesznek. Ezért a gyorsítótárazott termékadatokat nem csak a Products táblától, hanem a Categories és a Suppliers tábláktól is függővé szeretnénk tenni.

Az AggregateCacheDependency osztály lehetővé teszi, hogy több függőséget társítson egy gyorsítótárelemhez. Először hozzon létre egy példányt AggregateCacheDependency . Ezután adja hozzá a függőségek készletét az AggregateCacheDependency s Add metódussal. Amikor ezt követően beszúrja az elemet az adatgyorsítótárba, adja át a AggregateCacheDependency példányt. Ha a példány AggregateCacheDependency függősége megváltozik, a tárolt elem eltávolításra kerül.

Az alábbiakban az ProductsCL osztály AddCacheItem metódusának frissített kódját mutatjuk be. A metódus létrehozza a MasterCacheKeyArray gyorsítótár-függőséget a SqlCacheDependency objektumokkal a Products, Categories és Suppliers táblákhoz. Ezek mindegyike egyetlen AggregateCacheDependency , nevesített aggregateDependenciesobjektumba van összevonva, amelyet aztán átad a Insert metódusnak.

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);
}

Tesztelje ezt az új kódot. Most a Products, Categoriesvagy Suppliers táblák módosítása miatt a gyorsítótárazott adatok törlődnek. Ezenkívül az ProductsCL osztály UpdateProduct metódusa, amelyet egy termék GridView-on keresztüli szerkesztésekor hívunk meg, kiüríti a MasterCacheKeyArray gyorsítótár-függőséget, aminek következtében a gyorsítótár ProductsDataTable kiürül, és az adatokat újra lekérik a következő kérelemben.

Megjegyzés:

Az SQL Cache-függőségek a kimeneti gyorsítótárazással is használhatók. A funkció bemutatásához lásd: ASP.NET kimeneti gyorsítótárazás használata az SQL Serverrel.

Összefoglalás

Az adatbázisadatok gyorsítótárazásakor az adatok ideális esetben a gyorsítótárban maradnak, amíg azokat nem módosítják az adatbázisban. A 2.0-s ASP.NET sql-gyorsítótár-függőségek deklaratív és programozott forgatókönyvekben is létrehozhatók és használhatók. Ennek a megközelítésnek az egyik kihívása az adatok módosításának felderítése. A Microsoft SQL Server 2005 teljes verziói olyan értesítési képességeket biztosítanak, amelyek riasztást küldenek az alkalmazásnak a lekérdezés eredményének módosításakor. Az SQL Server 2005 Express Edition és az SQL Server régebbi verziói esetében ehelyett lekérdezési rendszert kell használni. Szerencsére a szükséges lekérdezési infrastruktúra beállítása meglehetősen egyszerű.

Boldog programozást!

További olvasás

Az oktatóanyagban tárgyalt témakörökről az alábbi forrásokban talál további információt:

Tudnivalók a szerzőről

Scott Mitchell, hét ASP/ASP.NET-könyv szerzője és a 4GuysFromRolla.com alapítója, 1998 óta dolgozik a Microsoft webtechnológiáival. Scott független tanácsadóként, edzőként és íróként dolgozik. Legújabb könyve Sams Tanuld meg ASP.NET 2.0 24 óra alatt. Ő itt elérhető mitchell@4GuysFromRolla.com.

Külön köszönet

Ezt az oktatóanyag-sorozatot sok hasznos véleményező áttekintette. Az oktatóanyag fő véleményezői Marko Rangel, Teresa Murphy és Hilton Giesenow voltak. Szeretné áttekinteni a közelgő MSDN-cikkeimet? Ha igen, írj egy sort a mitchell@4GuysFromRolla.com-ra.