Použití závislostí mezipaměti SQL (C#)
Nejjednodušší strategií ukládání do mezipaměti je umožnit vypršení platnosti dat uložených v mezipaměti po zadaném časovém období. Tento jednoduchý přístup ale znamená, že data uložená v mezipaměti si neudržují žádnou spojitost se svým podkladovým zdrojem dat, což vede k příliš dlouhým zastaralým datům nebo k vypršení jejich platnosti příliš brzy. Lepším přístupem je použití třídy SqlCacheDependency, aby data zůstala uložená v mezipaměti, dokud se jejich podkladová data nezmění v databázi SQL. V tomto kurzu se dozvíte, jak na to.
Úvod
Techniky ukládání do mezipaměti, které se zkoumaly v části Ukládání dat do mezipaměti s objectDataSource a Ukládání dat do mezipaměti v kurzech Architektury, používaly vypršení platnosti na základě času k vyřazení dat z mezipaměti po zadané době. Tento přístup představuje nejjednodušší způsob, jak vyvážit zvýšení výkonu při ukládání do mezipaměti a neaktuálnost dat. Výběrem časového limitu x sekund vývojář stránky připouští, že může využívat výhody výkonu ukládání do mezipaměti pouze x sekund, ale může si odpočinout, že data nikdy nebudou zastaralá déle než maximálně x sekund. U statických dat je samozřejmě možné x prodloužit na dobu životnosti webové aplikace, jak jsme si prohlédli v kurzu Ukládání dat do mezipaměti při spuštění aplikace .
Při ukládání dat databáze do mezipaměti se často volí vypršení platnosti na základě času z důvodu snadného použití, ale často se jedná o nedostatečné řešení. V ideálním případě by data databáze zůstala uložena v mezipaměti, dokud nebudou podkladová data v databázi změněna; pak by se mezipaměť vyřadila. Tento přístup maximalizuje výkonové výhody ukládání do mezipaměti a minimalizuje dobu trvání zastaralých dat. Aby však bylo možné tyto výhody využívat, musí existovat systém, který ví, kdy byla podkladová data databáze upravena, a vyřadí odpovídající položky z mezipaměti. Před ASP.NET 2.0 byli vývojáři stránek zodpovědní za implementaci tohoto systému.
ASP.NET 2.0 poskytuje SqlCacheDependency
třídu a potřebnou infrastrukturu pro určení, kdy došlo ke změně v databázi, aby bylo možné vyřadit odpovídající položky uložené v mezipaměti. Existují dvě techniky, jak určit, kdy se podkladová data změnila: oznámení a dotazování. Po probrání rozdílů mezi oznámením a dotazováním vytvoříme infrastrukturu potřebnou k podpoře dotazování a pak prozkoumáme, jak třídu používat SqlCacheDependency
v deklarativních a programových scénářích.
Principy oznámení a dotazování
Existují dvě techniky, které lze použít k určení, kdy byla data v databázi změněna: oznámení a dotazování. S oznámením databáze automaticky upozorní modul runtime ASP.NET, když se od posledního spuštění dotazu změnily výsledky konkrétního dotazu a v tomto okamžiku se položky v mezipaměti přidružené k dotazu vyřadí. Při dotazování databázový server udržuje informace o tom, kdy byly konkrétní tabulky naposledy aktualizovány. Modul runtime ASP.NET se pravidelně dotazuje databáze, aby zkontroloval, jaké tabulky se změnily od jejich zadání do mezipaměti. U tabulek, jejichž data byla změněna, se vyřadí přidružené položky mezipaměti.
Možnost oznámení vyžaduje méně nastavení než dotazování a je podrobnější, protože sleduje změny na úrovni dotazu, nikoli na úrovni tabulky. Oznámení jsou bohužel k dispozici pouze v úplných edicích Microsoft SQL Server 2005 (tj. edicích, které nejsou Express). Možnost dotazování se ale dá použít pro všechny verze Microsoft SQL Server od 7.0 do 2005. Vzhledem k tomu, že tyto kurzy používají edici Express SQL Server 2005, zaměříme se na nastavení a použití možnosti dotazování. Další zdroje informací o možnostech oznámení SQL Server 2005 najdete v části Další materiály na konci tohoto kurzu.
Při dotazování musí být databáze nakonfigurovaná tak, aby obsahovala tabulku s názvem AspNet_SqlCacheTablesForChangeNotification
, která má tři sloupce – tableName
, notificationCreated
a changeId
. Tato tabulka obsahuje řádek pro každou tabulku obsahující data, která může být potřeba použít v závislosti mezipaměti SQL ve webové aplikaci. Sloupec tableName
určuje název tabulky a zároveň notificationCreated
označuje datum a čas, kdy byl řádek přidán do tabulky. Sloupec changeId
je typu int
a má počáteční hodnotu 0. Jeho hodnota se s každou úpravou tabulky navyšuje.
Kromě AspNet_SqlCacheTablesForChangeNotification
tabulky musí databáze také obsahovat aktivační události pro každou z tabulek, které se můžou objevit v závislosti mezipaměti SQL. Tyto triggery se spustí při každém vložení, aktualizaci nebo odstranění řádku a zvýšení hodnoty tabulky changeId
v AspNet_SqlCacheTablesForChangeNotification
.
Modul runtime ASP.NET sleduje aktuální stav changeId
tabulky při ukládání dat do mezipaměti pomocí objektu SqlCacheDependency
. Databáze je pravidelně kontrolována a všechny SqlCacheDependency
objekty, jejichž changeId
se liší od hodnoty v databázi, jsou vyřazeny, protože odlišná changeId
hodnota značí, že od uložení dat do mezipaměti došlo ke změně tabulky.
Krok 1: Prozkoumání programu příkazovéhoaspnet_regsql.exe
řádku
U přístupu s dotazováním musí být databáze nastavená tak, aby obsahovala infrastrukturu popsanou výše: předdefinovanou tabulku (AspNet_SqlCacheTablesForChangeNotification
), několik uložených procedur a triggery pro každou z tabulek, které se dají použít v závislostech mezipaměti SQL ve webové aplikaci. Tyto tabulky, uložené procedury a triggery lze vytvořit prostřednictvím programu aspnet_regsql.exe
příkazového řádku , který se nachází ve $WINDOWS$\Microsoft.NET\Framework\version
složce . Pokud chcete vytvořit AspNet_SqlCacheTablesForChangeNotification
tabulku a přidružené uložené procedury, spusťte z příkazového řádku následující příkaz:
/* 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
Poznámka
Aby bylo možné tyto příkazy spustit, musí být zadané přihlášení k databázi v rolích db_securityadmin
a db_ddladmin
.
Pokud například chcete přidat infrastrukturu pro dotazování do databáze Microsoft SQL Server s názvem pubs
na databázovém serveru s názvem ScottsServer
pomocí ověřování systému Windows, přejděte do příslušného adresáře a z příkazového řádku zadejte:
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
Po přidání infrastruktury na úrovni databáze musíme do těchto tabulek přidat triggery, které se budou používat v závislostech mezipaměti SQL. Znovu použijte program příkazového aspnet_regsql.exe
řádku, ale zadejte název tabulky pomocí -t
přepínače a místo -ed
přepínače použijte -et
, například takto:
/* 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
Pokud chcete přidat triggery do authors
tabulek a titles
v databázi na pubs
ScottsServer
, použijte:
aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et
Pro účely tohoto kurzu přidejte triggery do Products
tabulek , Categories
a Suppliers
. Na konkrétní syntaxi příkazového řádku se podíváme v kroku 3.
Krok 2: Odkazování na databázi Microsoft SQL Server 2005 Express Edition vApp_Data
Program aspnet_regsql.exe
příkazového řádku vyžaduje název databáze a serveru, aby mohl přidat potřebnou infrastrukturu dotazování. Jaký je ale název databáze a serveru pro databázi Microsoft SQL Server 2005 Express, která se nachází ve App_Data
složce? Místo toho, abyste museli zjišťovat názvy databází a serverů, zjistil jsem, že nejjednodušším přístupem je připojit databázi k localhost\SQLExpress
instanci databáze a přejmenovat data pomocí SQL Server Management Studio. Pokud máte na počítači nainstalovanou jednu z úplných verzí SQL Server 2005, pravděpodobně už máte v počítači nainstalovanou SQL Server Management Studio. Pokud máte jenom edici Express, můžete si stáhnout bezplatnou verzi Microsoft SQL Server Management Studio Express Edition.
Začněte zavřením sady Visual Studio. Pak otevřete SQL Server Management Studio a zvolte připojení k localhost\SQLExpress
serveru pomocí ověřování systému Windows.
Obrázek 1: Připojení k localhost\SQLExpress
serveru
Po připojení k serveru management Studio zobrazí server a podsložky pro databáze, zabezpečení atd. Klikněte pravým tlačítkem na složku Databáze a zvolte možnost Připojit. Zobrazí se dialogové okno Připojit databáze (viz obrázek 2). Klikněte na tlačítko Přidat a vyberte NORTHWND.MDF
složku databáze ve složce s vaší webové aplikace App_Data
.
Obrázek 2: Připojení NORTHWND.MDF
databáze ze App_Data
složky (kliknutím zobrazíte obrázek v plné velikosti)
Tím se databáze přidá do složky Databáze. Název databáze může být úplná cesta k souboru databáze nebo úplná cesta s identifikátorem GUID. Abyste nemuseli při použití nástroje aspnet_regsql.exe příkazového řádku zadávat tento dlouhý název databáze, přejmenujte databázi na uživatelsky přívětivější název tak, že kliknete pravým tlačítkem na právě připojenou databázi a zvolíte Přejmenovat. Přejmenoval(a) jsem svou databázi na DataTutorials .
Obrázek 3: Přejmenování připojené databáze na další Human-Friendly název
Krok 3: Přidání infrastruktury dotazování do databáze Northwind
Teď, když jsme připojili NORTHWND.MDF
databázi ze App_Data
složky, jsme připraveni přidat infrastrukturu dotazování. Za předpokladu, že jste databázi přejmenovali na DataTutorials, spusťte následující čtyři příkazy:
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
Po spuštění těchto čtyř příkazů klikněte pravým tlačítkem na název databáze v management studiu, přejděte do podnabídky Úlohy a zvolte Odpojit. Pak zavřete Management Studio a znovu otevřete Sadu Visual Studio.
Po opětovném otevření sady Visual Studio přejděte k podrobnostem databáze prostřednictvím Průzkumníka serveru. Všimněte si nové tabulky (AspNet_SqlCacheTablesForChangeNotification
), nových uložených procedur a triggerů v Products
tabulkách , Categories
a Suppliers
.
Obrázek 4: Databáze teď zahrnuje potřebnou infrastrukturu dotazování
Krok 4: Konfigurace služby dotazování
Po vytvoření potřebných tabulek, triggerů a uložených procedur v databázi je posledním krokem konfigurace služby dotazování, kterou provedete Web.config
zadáním databází, které se mají použít, a frekvence dotazování v milisekundách. Následující kód dotazuje databázi Northwind jednou za sekundu.
<?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>
Hodnota name
v elementu <add>
( NorthwindDB ) přidruží název čitelný pro člověka ke konkrétní databázi. Při práci se závislostmi mezipaměti SQL budeme muset odkazovat na zde definovaný název databáze a také na tabulku, na které jsou založená data uložená v mezipaměti. V kroku 6 uvidíme, jak pomocí SqlCacheDependency
třídy programově přidružit závislosti mezipaměti SQL k datům uloženým v mezipaměti.
Po vytvoření závislosti mezipaměti SQL se systém dotazování připojí k databázím definovaným v <databases>
prvcích každých pollTime
milisekund a spustí uloženou proceduru AspNet_SqlCachePollingStoredProcedure
. Tato uložená procedura, která byla přidána zpět v kroku 3 pomocí nástroje příkazového aspnet_regsql.exe
řádku , vrátí tableName
hodnoty a changeId
pro každý záznam v AspNet_SqlCacheTablesForChangeNotification
souboru . Zastaralé závislosti mezipaměti SQL se z mezipaměti vyřadí.
Nastavení pollTime
zavádí kompromis mezi výkonem a zastaralostí dat. Malá pollTime
hodnota zvýší počet požadavků na databázi, ale rychleji vyřadí zastaralá data z mezipaměti. Větší pollTime
hodnota snižuje počet databázových požadavků, ale zvyšuje zpoždění mezi změnami dat back-endu a vyřazením souvisejících položek mezipaměti. Databázový požadavek naštěstí spouští jednoduchou uloženou proceduru, která vrací jen několik řádků z jednoduché, zjednodušené tabulky. Experimentujte ale s různými pollTime
hodnotami, abyste našli ideální rovnováhu mezi přístupem k databázi a zastaralostí dat pro vaši aplikaci. Nejmenší pollTime
povolená hodnota je 500.
Poznámka
Výše uvedený příklad poskytuje jednu pollTime
hodnotu v elementu <sqlCacheDependency>
, ale volitelně můžete zadat pollTime
hodnotu v elementu <add>
. To je užitečné, pokud máte zadaných více databází a chcete přizpůsobit frekvenci dotazování na databázi.
Krok 5: Deklarativní práce se závislostmi mezipaměti SQL
V krocích 1 až 4 jsme se podívali na to, jak nastavit potřebnou infrastrukturu databáze a nakonfigurovat systém dotazování. Díky této infrastruktuře teď můžeme přidávat položky do mezipaměti dat s přidruženou závislostí mezipaměti SQL pomocí programových nebo deklarativních technik. V tomto kroku prozkoumáme, jak deklarativně pracovat se závislostmi mezipaměti SQL. V kroku 6 se podíváme na programový přístup.
Kurz Ukládání dat do mezipaměti pomocí ObjectDataSource prozkoumal možnosti deklarativního ukládání do mezipaměti objectDataSource. Když jednoduše nastavíte EnableCaching
vlastnost na true
a CacheDuration
vlastnost na určitý časový interval, ObjectDataSource automaticky uloží data vrácená ze svého podkladového objektu do mezipaměti po zadaný interval. ObjectDataSource může také použít jednu nebo více závislostí mezipaměti SQL.
Chcete-li demonstrovat použití závislostí mezipaměti SQL deklarativně, otevřete SqlCacheDependencies.aspx
stránku ve Caching
složce a přetáhněte Objekt GridView z panelu nástrojů na Designer. Nastavte Objekt GridView ID
na ProductsDeclarative
a z jeho inteligentní značky zvolte, že se má vytvořit vazba na nový objekt ObjectDataSource s názvem ProductsDataSourceDeclarative
.
Obrázek 5: Vytvoření nového objektuDataSource s názvem ProductsDataSourceDeclarative
(kliknutím zobrazíte obrázek v plné velikosti)
Nakonfigurujte ObjectDataSource tak, aby používal ProductsBLL
třídu , a nastavte rozevírací seznam na kartě SELECT na GetProducts()
. Na kartě UPDATE zvolte přetížení se třemi UpdateProduct
vstupními parametry – productName
, unitPrice
a productID
. Na kartách VLOŽENÍ a ODSTRANIT nastavte rozevírací seznamy na (Žádný).
Obrázek 6: Použití přetížení UpdateProduct se třemi vstupními parametry (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 7: Nastavení seznamu Drop-Down na (Žádný) pro karty INSERT a DELETE (Kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Konfigurovat zdroj dat vytvoří Visual Studio v zobrazení GridView pro každé z datových polí BoundFields a CheckBoxFields. Odeberte všechna pole kromě ProductName
, CategoryName
a UnitPrice
naformátujte je podle potřeby. V inteligentní značce GridView zaškrtněte políčka Povolit stránkování, Povolit řazení a Povolit úpravy. Visual Studio nastaví vlastnost ObjectDataSource na OldValuesParameterFormatString
original_{0}
. Aby funkce úprav objektu GridView fungovala správně, odeberte tuto vlastnost zcela z deklarativní syntaxe nebo ji nastavte zpět na výchozí hodnotu . {0}
Nakonec přidejte ovládací prvek Label Web nad GridView a nastavte jeho ID
vlastnost na ODSEvents
a jeho EnableViewState
vlastnost na false
. Po provedení těchto změn by deklarativní kód stránky měl vypadat nějak takto. Všimněte si, že jsem provedl řadu estetických přizpůsobení polí GridView, které nejsou nutné k předvedení funkce závislostí mezipaměti SQL.
<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>
Dále vytvořte obslužnou rutinu události objectDataSource Selecting
a přidejte do ní následující kód:
protected void ProductsDataSourceDeclarative_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
ODSEvents.Text = "-- Selecting event fired";
}
Vzpomeňte si, že událost ObjectDataSource se Selecting
aktivuje pouze při načítání dat ze svého podkladového objektu. Pokud ObjectDataSource přistupuje k datům z vlastní mezipaměti, tato událost se neaktivuje.
Teď přejděte na tuto stránku prostřednictvím prohlížeče. Vzhledem k tomu, že jsme ještě neimplementovali ukládání do mezipaměti, měla by se při každé stránce, řazení nebo úpravě mřížky zobrazit text "Aktivována událost výběru, jak je znázorněno na obrázku 8.
Obrázek 8: Událost ObjectDataSource se Selecting
aktivuje pokaždé, když je objekt GridView stránkovaný, upravený nebo seřazený (kliknutím zobrazíte obrázek v plné velikosti).
Jak jsme viděli v kurzu Ukládání dat do mezipaměti pomocí ObjectDataSource , nastavení EnableCaching
vlastnosti na true
způsobí, že ObjectDataSource bude ukládat data do mezipaměti po dobu určenou jeho CacheDuration
vlastností. ObjectDataSource má SqlCacheDependency
také vlastnost , která přidá jednu nebo více závislostí mezipaměti SQL k datům uloženým v mezipaměti pomocí vzoru :
databaseName1:tableName1;databaseName2:tableName2;...
Kde databaseName je název databáze zadaný v atributu name
elementu <add>
v Web.config
a tableName je název databázové tabulky. Chcete-li například vytvořit ObjectDataSource, který ukládá data do mezipaměti po neomezenou dobu na základě závislosti mezipaměti SQL s tabulky Northwind Products
, nastavte vlastnost ObjectDataSource na EnableCaching
true
a jeho SqlCacheDependency
vlastnost na NorthwindDB:Products .
Poznámka
Můžete použít závislost mezipaměti SQL a vypršení platnosti podle času tak, že nastavíte EnableCaching
na true
, CacheDuration
na časový interval a SqlCacheDependency
na názvy databází a tabulek. ObjectDataSource vyřadí svá data, když dojde k vypršení platnosti na základě času nebo když systém dotazování zaznamená, že se podkladová data databáze změnila, podle toho, co nastane dříve.
Objekt GridView v SqlCacheDependencies.aspx
nástroji zobrazí data ze dvou tabulek – Products
a Categories
(pole product s CategoryName
se načte pomocí operátoru JOIN
).Categories
Proto chceme zadat dvě závislosti mezipaměti SQL: NorthwindDB:Products; NorthwindDB:Categories .
Obrázek 9: Konfigurace objektu ObjectDataSource pro podporu ukládání do mezipaměti pomocí závislostí mezipaměti SQL na Products
a Categories
(Kliknutím zobrazíte obrázek v plné velikosti)
Po nakonfigurování objektu ObjectDataSource tak, aby podporoval ukládání do mezipaměti, přejděte znovu na stránku v prohlížeči. Znovu platí, že text "Výběr události aktivované" by se měl objevit při první návštěvě stránky, ale při stránkování, řazení nebo kliknutí na tlačítka Upravit nebo Zrušit by měl zminout. Je to proto, že po načtení dat do mezipaměti ObjectDataSource, zůstanou tam, dokud Products
nejsou změněny nebo tabulky nebo Categories
data aktualizována prostřednictvím GridView.
Po procházení mřížky a upozornění na chybějící text "Výběr události aktivovaného textu, otevřete nové okno prohlížeče a přejděte na kurz Základy v části Úpravy, vkládání a odstraňování (~/EditInsertDelete/Basics.aspx
). Aktualizujte název nebo cenu produktu. Potom z prvního okna prohlížeče zobrazte jinou stránku dat, seřaďte mřížku nebo klikněte na tlačítko Upravit na řádku. Tentokrát by se měla znovu zobrazit událost výběru, protože se změnila podkladová data databáze (viz Obrázek 10). Pokud se text nezobrazí, chvíli počkejte a zkuste to znovu. Mějte na paměti, že služba dotazování kontroluje změny Products
tabulky každých pollTime
milisekund, takže mezi aktualizací podkladových dat a vyřazením dat v mezipaměti je prodleva.
Obrázek 10: Úprava tabulky Products vyřadí data produktů uložená v mezipaměti (kliknutím zobrazíte obrázek v plné velikosti)
Krok 6: Práce s třídou prostřednictvímSqlCacheDependency
kódu programu
Ukládání dat do mezipaměti v kurzu Architektura se zabývalo výhodami použití samostatné vrstvy ukládání do mezipaměti v architektuře oproti těsnému propojení ukládání do mezipaměti s objektem ObjectDataSource. V tomto kurzu jsme vytvořili ProductsCL
třídu, která předvádí programovou práci s mezipamětí dat. Pokud chcete využít závislosti mezipaměti SQL ve vrstvě ukládání do mezipaměti, použijte SqlCacheDependency
třídu .
V systému SqlCacheDependency
dotazování musí být objekt přidružený ke konkrétnímu páru databáze a tabulky. Následující kód například vytvoří SqlCacheDependency
objekt založený na tabulce databáze Products
Northwind:
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
Dva vstupní parametry konstruktoru SqlCacheDependency
s jsou názvy databáze a tabulky v uvedeném pořadí. Stejně jako u vlastnosti ObjectDataSource s SqlCacheDependency
je použitý název databáze stejný jako hodnota zadaná v name
atributu elementu <add>
v Web.config
. Název tabulky je skutečný název tabulky databáze.
Chcete-li přidružit SqlCacheDependency
položku přidanou do mezipaměti dat, použijte jedno z Insert
přetížení metody, které přijímají závislost. Následující kód přidá hodnotu do mezipaměti dat po neomezenou dobu, ale přidruží ji k objektu SqlCacheDependency
v Products
tabulce. Stručně řečeno, hodnota zůstane v mezipaměti, dokud nebude vyřazena z důvodu omezení paměti nebo protože systém dotazování zjistil, že Products
se tabulka od uložení do mezipaměti změnila.
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key,
value,
productsTableDependency,
System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration);
Třída Vrstva ProductsCL
ukládání do mezipaměti aktuálně ukládá data z Products
tabulky do mezipaměti s využitím vypršení 60 sekund podle času. Pojďme aktualizovat tuto třídu tak, aby místo toho používala závislosti mezipaměti SQL. Metoda ProductsCL
třídy s AddCacheItem
, která je zodpovědná za přidání dat do mezipaměti, aktuálně obsahuje následující kód:
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);
}
Aktualizujte tento kód tak, SqlCacheDependency
aby místo MasterCacheKeyArray
závislosti mezipaměti používal objekt:
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);
}
Chcete-li otestovat tuto funkci, přidejte GridView na stránku pod existující ProductsDeclarative
GridView. Nastavte tento nový Objekt GridView ID
na ProductsProgrammatic
a prostřednictvím jeho inteligentní značky vytvořte vazbu k novému objektu ObjectDataSource s názvem ProductsDataSourceProgrammatic
. Nakonfigurujte ObjectDataSource tak, aby používal ProductsCL
třídu , a nastavte rozevírací seznamy na kartách SELECT a UPDATE na GetProducts
a UpdateProduct
v uvedeném pořadí.
Obrázek 11: Konfigurace objektu ObjectDataSource pro použití ProductsCL
třídy (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 12: Výběr GetProducts
metody ze seznamu select tab s Drop-Down (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 13: Výběr metody UpdateProduct ze seznamu Drop-Down karet UPDATE (kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Konfigurovat zdroj dat vytvoří Visual Studio v zobrazení GridView pro každé z datových polí BoundFields a CheckBoxFields. Stejně jako u prvního objektu GridView přidaného na tuto stránku odeberte všechna pole kromě ProductName
, CategoryName
a UnitPrice
naformátujte tato pole podle potřeby. V inteligentní značce GridView zaškrtněte políčka Povolit stránkování, Povolit řazení a Povolit úpravy. Stejně jako u objektu ProductsDataSourceDeclarative
ObjectDataSource nastaví ProductsDataSourceProgrammatic
Visual Studio vlastnost ObjectDataSource OldValuesParameterFormatString
na original_{0}
. Aby funkce úprav objektu GridView fungovala správně, nastavte tuto vlastnost zpět na {0}
(nebo úplně odeberte přiřazení vlastnosti z deklarativní syntaxe).
Po dokončení těchto úloh by měl výsledný deklarativní kód GridView a ObjectDataSource vypadat takto:
<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>
Pokud chcete otestovat závislost mezipaměti SQL ve vrstvě ukládání do mezipaměti, nastavte zarážku v ProductCL
metodě třídy s AddCacheItem
a pak spusťte ladění. Při první návštěvě SqlCacheDependencies.aspx
by se zarážka měla zobrazit, protože se data poprvé požadují a umístí do mezipaměti. Dále přejděte na jinou stránku v zobrazení GridView nebo seřaďte jeden ze sloupců. To způsobí, že GridView znovu dotazuje data, ale data by měla být nalezena v mezipaměti, protože Products
tabulka databáze nebyla změněna. Pokud se data v mezipaměti opakovaně nenašla, ujistěte se, že je v počítači k dispozici dostatek paměti, a zkuste to znovu.
Po procházení několika stránek objektu GridView otevřete druhé okno prohlížeče a přejděte na kurz Základy v části Úpravy, vkládání a odstraňování (~/EditInsertDelete/Basics.aspx
). Aktualizujte záznam z tabulky Products a pak v prvním okně prohlížeče zobrazte novou stránku nebo klikněte na jedno z záhlaví řazení.
V tomto scénáři uvidíte jednu ze dvou věcí: buď dojde k dosažení zarážky, což znamená, že data uložená v mezipaměti byla vyřazena z důvodu změny v databázi; nebo se zarážka nenarazí, což znamená, že SqlCacheDependencies.aspx
se teď zobrazují zastaralá data. Pokud se zarážka nedosáhne, je pravděpodobné, že se služba dotazování od změny dat ještě neaktivovala. Mějte na paměti, že služba dotazování kontroluje změny Products
tabulky každých pollTime
milisekund, takže mezi aktualizací podkladových dat a vyřazením dat v mezipaměti je prodleva.
Poznámka
Toto zpoždění se s větší pravděpodobností objeví při úpravách některého z produktů prostřednictvím objektu GridView v SqlCacheDependencies.aspx
. V kurzu Architektura jsme přidali MasterCacheKeyArray
závislost mezipaměti, abychom zajistili, že se data upravovaná pomocí ProductsCL
metody třídy s UpdateProduct
vyřadí z mezipaměti. Tuto závislost mezipaměti jsme však nahradili při úpravě AddCacheItem
metody dříve v tomto kroku, a proto ProductsCL
bude třída dál zobrazovat data uložená v mezipaměti, dokud systém dotazování změnu tabulky nepoznamená Products
. V kroku 7 se podíváme MasterCacheKeyArray
, jak znovu zavést závislost mezipaměti.
Krok 7: Přidružení více závislostí k položce v mezipaměti
Vzpomeňte MasterCacheKeyArray
si, že závislost mezipaměti se používá k zajištění toho, aby se všechna data související s produktem vyřadila z mezipaměti, když se aktualizují všechny položky přidružené k mezipaměti. Metoda například GetProductsByCategoryID(categoryID)
ukládá ProductsDataTables
instance do mezipaměti pro každou jedinečnou hodnotu categoryID . Pokud se jeden z těchto objektů vyřadí, MasterCacheKeyArray
závislost mezipaměti zajistí, že se odeberou i ostatní objekty. Bez této závislosti na mezipaměti existuje při změně dat uložených v mezipaměti možnost, že ostatní produktová data uložená v mezipaměti můžou být za aktuální. V důsledku toho je důležité udržovat MasterCacheKeyArray
závislost mezipaměti při použití závislostí mezipaměti SQL. Metoda mezipaměti Insert
dat však umožňuje pouze jeden objekt závislosti.
Při práci se závislostmi mezipaměti SQL navíc možná budeme muset jako závislosti přidružit více databázových tabulek. Například ProductsDataTable
objekt uložený v mezipaměti ve ProductsCL
třídě obsahuje názvy kategorií a dodavatelů pro každý produkt, ale AddCacheItem
metoda používá pouze závislost na Products
. V takové situaci, pokud uživatel aktualizuje název kategorie nebo dodavatele, zůstanou data produktů uložená v mezipaměti a budou za aktuální. Proto chceme, aby produktová data uložená v mezipaměti závisela nejen Products
na tabulce, ale také na Categories
tabulkách a Suppliers
.
TřídaAggregateCacheDependency
poskytuje prostředky pro přidružení více závislostí k položce mezipaměti. Začněte vytvořením AggregateCacheDependency
instance. Dále přidejte sadu závislostí pomocí AggregateCacheDependency
metody s Add
. Při následném vložení položky do mezipaměti dat předejte AggregateCacheDependency
instanci . Když se AggregateCacheDependency
změní některá ze závislostí instance, položka uložená v mezipaměti se vyřadí.
Následující příklad ukazuje aktualizovaný kód pro metodu ProductsCL
třídy s AddCacheItem
. Metoda vytvoří MasterCacheKeyArray
závislost mezipaměti spolu s SqlCacheDependency
objekty pro Products
tabulky , Categories
a Suppliers
. Všechny jsou sloučené do jednoho AggregateCacheDependency
objektu s názvem aggregateDependencies
, který se pak předá metodě Insert
.
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);
}
Otestujte tento nový kód. Změny Products
tabulek , Categories
nebo Suppliers
teď způsobí vyřazení dat uložených v mezipaměti. Kromě toho ProductsCL
metoda třídy s UpdateProduct
, která se volá při úpravách produktu prostřednictvím GridView, vyřazuje MasterCacheKeyArray
závislost mezipaměti, což způsobí vyřazení ProductsDataTable
mezipaměti a opětovné načtení dat při dalším požadavku.
Poznámka
Závislosti mezipaměti SQL je možné použít také s ukládáním výstupu do mezipaměti. Ukázku této funkce najdete v tématu Použití ASP.NET ukládání výstupu do mezipaměti s SQL Server.
Souhrn
Při ukládání dat databáze do mezipaměti data v ideálním případě zůstanou v mezipaměti, dokud se v databázi nezmění. V ASP.NET 2.0 je možné vytvářet a používat závislosti mezipaměti SQL v deklarativních i programových scénářích. Jednou z výzev tohoto přístupu je zjištění, kdy byla data změněna. Plné verze Microsoft SQL Server 2005 poskytují možnosti oznámení, které mohou aplikaci upozornit při změně výsledku dotazu. Pro Express Edition SQL Server 2005 a starší verze SQL Server, musí být místo toho použit systém dotazování. Nastavení potřebné infrastruktury dotazování je naštěstí poměrně jednoduché.
Všechno nejlepší na programování!
Další čtení
Další informace o tématech probíraných v tomto kurzu najdete v následujících zdrojích informací:
- Použití oznámení dotazů v Microsoft SQL Server 2005
- Vytvoření oznámení dotazu
- Ukládání do mezipaměti v ASP.NET pomocí
SqlCacheDependency
třídy - nástroj pro registraci ASP.NET SQL Server (
aspnet_regsql.exe
) - Přehled
SqlCacheDependency
O autorovi
Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.
Zvláštní poděkování
Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Marko Rangel, Teresa Murphy a Hilton Giesenow. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.