Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
La strategia di memorizzazione nella cache più semplice consiste nel consentire la scadenza dei dati memorizzati nella cache dopo un periodo di tempo specificato. Tuttavia, questo approccio semplice implica che i dati memorizzati nella cache non mantengono alcuna associazione con la loro origine dati sottostante, portando a dati obsoleti trattenuti troppo a lungo o dati attuali che scadono troppo presto. Un approccio migliore consiste nell'usare la classe SqlCacheDependency in modo che i dati rimangano memorizzati nella cache fino a quando i dati sottostanti non vengono modificati nel database SQL. Questa esercitazione illustra come.
Introduzione
Le tecniche di memorizzazione nella cache esaminate nei tutorial Memorizzazione nella cache dei dati con ObjectDataSource e Memorizzazione nella cache dei dati nell'architettura hanno utilizzato una scadenza basata sul tempo per rimuovere i dati dalla cache dopo un periodo specificato. Questo approccio è il modo più semplice per bilanciare i miglioramenti delle prestazioni della memorizzazione nella cache rispetto al decadimento dei dati. Selezionando una scadenza temporale di x secondi, uno sviluppatore di pagine concede di usufruire dei vantaggi della memorizzazione nella cache per solo x secondi, ma può riposare facilmente che i dati non saranno mai obsoleti più di un massimo di x secondi. Naturalmente, per i dati statici, x può essere esteso alla durata dell'applicazione Web, come è stato esaminato nell'esercitazione Memorizzazione nella cache dei dati all'avvio dell'applicazione .
Quando si memorizzano nella cache i dati del database, viene spesso scelta una scadenza basata sul tempo per facilitarne l'uso, ma spesso è una soluzione inadeguata. Idealmente, i dati del database rimarranno memorizzati nella cache fino a quando i dati sottostanti non sono stati modificati nel database; solo allora la cache verrà rimossa. Questo approccio ottimizza i vantaggi delle prestazioni della memorizzazione nella cache e riduce al minimo la durata dei dati non aggiornati. Tuttavia, per usufruire di questi vantaggi, è necessario che sia presente un sistema che sappia quando i dati del database sottostanti sono stati modificati ed espelle gli elementi corrispondenti dalla cache. Prima di ASP.NET 2.0, gli sviluppatori di pagine erano responsabili dell'implementazione di questo sistema.
ASP.NET 2.0 fornisce una SqlCacheDependency classe e l'infrastruttura necessaria per determinare quando si è verificata una modifica nel database in modo che gli elementi memorizzati nella cache corrispondenti possano essere rimossi. Esistono due tecniche per determinare quando i dati sottostanti sono stati modificati: notifica e polling. Dopo aver discusso delle differenze tra notifica e polling, si creerà l'infrastruttura necessaria per supportare il polling e quindi si esaminerà come usare la SqlCacheDependency classe in scenari dichiarativi e a livello di codice.
Informazioni sulle notifiche e sul polling
Esistono due tecniche che possono essere usate per determinare quando i dati in un database sono stati modificati: notifica e polling. Con la notifica, il database avvisa automaticamente il runtime ASP.NET quando i risultati di una determinata query sono stati modificati dopo l'ultima esecuzione della query, a quel punto gli elementi memorizzati nella cache associati alla query vengono rimossi. Con il polling, il server di database mantiene le informazioni relative all'ultimo aggiornamento di determinate tabelle. Il runtime ASP.NET esegue periodicamente il polling del database per verificare quali tabelle sono state modificate dopo l'immissione nella cache. Tali tabelle i cui dati sono stati modificati hanno rimosso gli elementi della cache associati.
L'opzione di notifica richiede meno installazione rispetto al polling ed è più granulare perché tiene traccia delle modifiche a livello di query anziché a livello di tabella. Sfortunatamente, le notifiche sono disponibili solo nelle edizioni complete di Microsoft SQL Server 2005 (ad esempio, le edizioni non Express). Tuttavia, l'opzione di polling può essere usata per tutte le versioni di Microsoft SQL Server da 7.0 a 2005. Poiché queste esercitazioni usano l'edizione Express di SQL Server 2005, ci si concentrerà sulla configurazione e sull'uso dell'opzione di polling. Vedere la sezione Altre informazioni alla fine di questa esercitazione per altre risorse sulle funzionalità di notifica di SQL Server 2005.
Con il polling, il database deve essere configurato per includere una tabella denominata AspNet_SqlCacheTablesForChangeNotification con tre colonne, tableName, notificationCreatede changeId. Questa tabella contiene una riga per ogni tabella con dati che potrebbero essere necessari in una dipendenza della cache SQL nell'applicazione Web. La tableName colonna specifica il nome della tabella, mentre notificationCreated indica la data e l'ora di aggiunta della riga alla tabella. La changeId colonna è di tipo int e ha un valore iniziale pari a 0. Il valore viene incrementato con ogni modifica alla tabella.
Oltre alla AspNet_SqlCacheTablesForChangeNotification tabella, il database deve includere anche trigger in ognuna delle tabelle che possono essere visualizzate in una dipendenza della cache SQL. Questi trigger vengono eseguiti ogni volta che una riga viene inserita, aggiornata o eliminata e incrementa il valore della tabella changeId in AspNet_SqlCacheTablesForChangeNotification.
Il runtime ASP.NET tiene traccia dell'oggetto corrente changeId per una tabella quando si memorizzano nella cache i dati usando un oggetto SqlCacheDependency. Il database viene controllato periodicamente e tutti SqlCacheDependency gli oggetti i cui changeId valori differiscono dal valore nel database vengono rimossi perché un valore diverso changeId indica che è stata apportata una modifica alla tabella dopo la memorizzazione nella cache dei dati.
Passaggio 1: Esplorazione del programma dellaaspnet_regsql.exeriga di comando
Con l'approccio di polling, il database deve essere configurato per contenere l'infrastruttura descritta sopra: una tabella predefinita (AspNet_SqlCacheTablesForChangeNotification), un certo numero di procedure memorizzate e trigger su ciascuna delle tabelle che possono essere utilizzati nelle dipendenze della cache SQL nell'applicazione web. Queste tabelle, le stored procedure e i trigger possono essere create tramite il programma aspnet_regsql.exe della riga di comando, disponibile nella cartella $WINDOWS$\Microsoft.NET\Framework\version. Per creare la AspNet_SqlCacheTablesForChangeNotification tabella e le stored procedure associate, eseguire quanto segue dalla riga di comando:
/* 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
Annotazioni
Per eseguire questi comandi, l'account di accesso al database specificato deve trovarsi nei ruoli db_securityadmin e db_ddladmin.
Ad esempio, per aggiungere l'infrastruttura per il polling a un database di Microsoft SQL Server denominato pubs in un server di database denominato ScottsServer usando l'autenticazione di Windows, passare alla directory appropriata e, dalla riga di comando, digitare:
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
Dopo aver aggiunto l'infrastruttura a livello di database, è necessario aggiungere i trigger alle tabelle che verranno usate nelle dipendenze della cache SQL. Usare di nuovo il programma della aspnet_regsql.exe riga di comando, ma specificare il nome della tabella usando l'opzione -t e invece di usare l'opzione -ed usare -et, come illustrato di seguito:
/* 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
Per aggiungere i trigger alle tabelle authors e titles nel database pubs su ScottsServer, usare:
aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et
Per questo tutorial, aggiungere i trigger alle tabelle Products, Categories e Suppliers. Si esaminerà la sintassi della riga di comando specifica nel passaggio 3.
Passaggio 2: Fare riferimento a un database Microsoft SQL Server 2005 Express Edition inApp_Data
Il aspnet_regsql.exe programma della riga di comando richiede il nome del database e del server per aggiungere l'infrastruttura di polling necessaria. Ma qual è il nome del database e del server per un database di Microsoft SQL Server 2005 Express che risiede nella App_Data cartella? Invece di dover individuare i nomi di database e server, si è scoperto che l'approccio più semplice consiste nel collegare il database all'istanza del localhost\SQLExpress database e rinominare i dati usando SQL Server Management Studio. Se nel computer è installata una delle versioni complete di SQL Server 2005, è probabile che nel computer sia già installato SQL Server Management Studio. Se si dispone solo dell'edizione Express, è possibile scaricare l'edizione Express di Microsoft SQL Server Management Studio gratuita.
Iniziare chiudendo Visual Studio. Aprire quindi SQL Server Management Studio e scegliere di connettersi al localhost\SQLExpress server usando l'autenticazione di Windows.
Figura 1: Connettersi al localhost\SQLExpress server
Dopo la connessione al server, Management Studio mostrerà il server e avrà sottocartelle per i database, la sicurezza e così via. Fare clic con il pulsante destro del mouse sulla cartella Database e scegliere l'opzione Collega. Verrà visualizzata la finestra di dialogo Collega database (vedere la figura 2). Fare clic sul pulsante Aggiungi e selezionare la NORTHWND.MDF cartella del database nella cartella dell'applicazione App_Data Web.
Figura 2: Collegare il NORTHWND.MDF database dalla App_Data cartella (fare clic per visualizzare l'immagine a dimensione intera)
Verrà aggiunto il database alla cartella Database. Il nome del database potrebbe essere il percorso completo del file di database o il percorso completo preceduto da un GUID. Per evitare di dover digitare questo nome lungo del database quando si usa lo strumento da riga di comando aspnet_regsql.exe, rinominare il database con un nome più descrittivo facendo clic con il pulsante destro del mouse sul database appena collegato e scegliendo Rinomina. Il database è stato rinominato in DataTutorials.
Figura 3: Rinominare il database collegato con un nome più significativo Human-Friendly
Passaggio 3: Aggiunta dell'infrastruttura di polling al database Northwind
Ora che abbiamo collegato il database NORTHWND.MDF dalla cartella App_Data, siamo pronti ad aggiungere l'infrastruttura di polling. Supponendo di aver rinominato il database in DataTutorials, eseguire i quattro comandi seguenti:
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
Dopo aver eseguito questi quattro comandi, fare clic con il pulsante destro del mouse sul nome del database in Management Studio, passare al sottomenu Attività e scegliere Scollega. Chiudere quindi Management Studio e riaprire Visual Studio.
Dopo aver riaperto Visual Studio, esplora il database tramite Esplora Server. Si noti la nuova tabella (AspNet_SqlCacheTablesForChangeNotification), le nuove stored procedure e i trigger sulle tabelle Products, Categories e Suppliers.
Figura 4: Il database include ora l'infrastruttura di polling necessaria
Passaggio 4: Configurazione del servizio di polling
Dopo aver creato le tabelle, i trigger e le stored procedure necessarie nel database, il passaggio finale consiste nel configurare il servizio di polling, che viene eseguito Web.config specificando i database da usare e la frequenza di polling in millisecondi. Il markup seguente interroga il database Northwind ogni secondo.
<?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>
Il name valore nell'elemento <add> ( NorthwindDB ) associa un nome comprensibile a un particolare database. Quando si riguardano le dipendenze della cache SQL, è necessario fare riferimento al nome del database definito qui e alla tabella su cui si basano i dati memorizzati nella cache. Si vedrà come usare la SqlCacheDependency classe per associare a livello di codice le dipendenze della cache SQL ai dati memorizzati nella cache nel passaggio 6.
Dopo aver stabilito una dipendenza della cache SQL, il sistema di polling si connetterà ai database definiti negli <databases> elementi ogni pollTime millisecondi ed eseguirà la AspNet_SqlCachePollingStoredProcedure procedura memorizzata. Questa stored procedure - che è stata aggiunta al passaggio 3 usando lo strumento da aspnet_regsql.exe riga di comando - restituisce i valori tableName e changeId per ogni record in AspNet_SqlCacheTablesForChangeNotification. Le dipendenze della cache SQL obsolete vengono rimosse dalla cache.
L'impostazione pollTime introduce un compromesso tra prestazioni e decadimento dei dati. Un valore ridotto pollTime aumenta il numero di richieste al database, ma rimuove più rapidamente i dati obsoleti dalla cache. Un valore maggiore pollTime riduce il numero di richieste di database, ma aumenta il ritardo tra la modifica dei dati back-end e la rimozione degli elementi della cache correlati. Fortunatamente, la richiesta di database esegue una semplice stored procedure che restituisce solo poche righe da una tabella semplice e leggera. Tuttavia, sperimentate con valori diversi pollTime per trovare un equilibrio ideale tra l'accesso al database e l'obsolescenza dei dati per l'applicazione. Il valore più pollTime piccolo consentito è 500.
Annotazioni
Nell'esempio precedente viene fornito un singolo pollTime valore nell'elemento <sqlCacheDependency> , ma facoltativamente è possibile specificare il pollTime valore nell'elemento <add> . Ciò è utile se sono stati specificati più database e si vuole personalizzare la frequenza di polling per ogni database.
Passaggio 5: Uso dichiarativo delle dipendenze della cache SQL
Nei passaggi da 1 a 4 è stato illustrato come configurare l'infrastruttura di database necessaria e configurare il sistema di polling. Con questa infrastruttura è ora possibile aggiungere elementi alla cache dei dati con una dipendenza della cache SQL associata usando tecniche programmatice o dichiarative. In questo passaggio si esaminerà come usare in modo dichiarativo le dipendenze della cache SQL. Nel passaggio 6 si esaminerà l'approccio programmatico.
L'esercitazione sulla memorizzazione nella cache dei dati con ObjectDataSource ha esplorato le capacità di caching dichiarativo dell'ObjectDataSource. Impostando semplicemente la EnableCaching proprietà su true e la CacheDuration proprietà su un intervallo di tempo, ObjectDataSource memorizza automaticamente nella cache i dati restituiti dall'oggetto sottostante per l'intervallo specificato. ObjectDataSource può anche usare una o più dipendenze della cache SQL.
Per illustrare l'uso delle dipendenze della cache SQL in modo dichiarativo, aprire la SqlCacheDependencies.aspx pagina nella Caching cartella e trascinare la GridView dalla casella degli strumenti nella finestra di progettazione. Impostare GridView s ID su ProductsDeclarative e, dallo smart tag, scegliere di associarlo a un nuovo ObjectDataSource denominato ProductsDataSourceDeclarative.
Figura 5: Creare un nuovo oggettoDataSource denominato ProductsDataSourceDeclarative (fare clic per visualizzare l'immagine a dimensione intera)
Configurare ObjectDataSource per usare la ProductsBLL classe e impostare l'elenco a discesa nella scheda SELECT su GetProducts(). Nella scheda UPDATE scegliere l'overload UpdateProduct con tre parametri di input : productName, unitPricee productID. Impostare gli elenchi a discesa su (Nessuno) nelle schede INSERT e DELETE.
Usare l'overload UpdateProduct con tre parametri di input
Figura 6: Usare l'overload di UpdateProduct con tre parametri di input (fare clic per visualizzare l'immagine a dimensione intera)
Figura 7: Impostare l'elenco di Drop-Down su (Nessuno) per le schede INSERT e DELETE (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata Configura origine dati, Visual Studio creerà BoundFields e CheckBoxFields in GridView per ognuno dei campi dati. Rimuovere tutti i campi, ma ProductName, CategoryNamee UnitPrice, e formattare questi campi nel modo desiderato. Dallo smart tag di GridView, selezionare le caselle di controllo Abilita paging, Abilita ordinamento e Abilita modifica. Visual Studio imposterà la proprietà OldValuesParameterFormatStringObjectDataSource su original_{0} Affinché la funzionalità di modifica di GridView funzioni correttamente, rimuovere completamente questa proprietà dalla sintassi dichiarativa o impostarla di nuovo sul valore predefinito, {0}.
Aggiungere infine un controllo Web Label sopra GridView e impostarne la ID proprietà su ODSEvents e la relativa EnableViewState proprietà su false. Dopo aver apportato queste modifiche, il markup dichiarativo della pagina dovrebbe essere simile al seguente. Si noti che sono state apportate numerose personalizzazioni estetiche ai campi GridView che non sono necessari per dimostrare la funzionalità di dipendenza della cache 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>
Creare quindi un gestore eventi per l'evento ObjectDataSource Selecting e aggiungere il codice seguente:
protected void ProductsDataSourceDeclarative_Selecting
(object sender, ObjectDataSourceSelectingEventArgs e)
{
ODSEvents.Text = "-- Selecting event fired";
}
Tenere presente che l'evento ObjectDataSource Selecting viene generato solo quando si recuperano dati dall'oggetto sottostante. Se ObjectDataSource accede ai dati dalla propria cache, questo evento non viene generato.
Visitare ora questa pagina tramite un browser. Poiché non è ancora stata implementata alcuna memorizzazione nella cache, ogni volta che si pagina, ordina o modifica la griglia, la pagina dovrebbe visualizzare il testo, "Evento di selezione attivato", come mostrato nella figura 8.
Figura 8: L'evento ObjectDataSource Selecting viene generato ogni volta che GridView è sottoposto a paging, modifica o ordinamento (fare clic per visualizzare l'immagine a dimensione intera)
Come illustrato nell'esercitazione Memorizzazione nella cache dei dati con ObjectDataSource, l'impostazione della EnableCaching proprietà su true fa sì che ObjectDataSource memorizza i dati nella cache per la durata specificata dalla relativa CacheDuration proprietà. ObjectDataSource dispone inoltre di una SqlCacheDependency proprietà che aggiunge una o più dipendenze della cache SQL ai dati memorizzati nella cache usando il modello :
databaseName1:tableName1;databaseName2:tableName2;...
Dove databaseName è il nome del database come specificato nell'attributo dell'elemento name<add> in Web.confige tableName è il nome della tabella di database. Ad esempio, per creare un ObjectDataSource che memorizza i dati nella cache in modo indefinito grazie a una dipendenza della cache SQL dalla tabella Northwind, impostare la proprietà Products di ObjectDataSource su EnableCaching e la sua proprietà true su NorthwindDB:Products.
Annotazioni
È possibile usare una dipendenza della cache SQL e una scadenza basata sul tempo impostando EnableCaching su true, CacheDuration sull'intervallo di tempo e SqlCacheDependency sui nomi del database e della tabella. ObjectDataSource rimuove i dati quando viene raggiunta la scadenza basata sul tempo o quando il sistema di polling rileva che i dati del database sottostanti sono stati modificati, a seconda di quale situazione si verifica per prima.
GridView in SqlCacheDependencies.aspx visualizza i dati da due tabelle: Products e Categories (il campo CategoryName del prodotto viene recuperato tramite un JOIN su Categories). Di conseguenza, si vogliono specificare due dipendenze della cache SQL: NorthwindDB:Products; NorthwindDB:Categories .
Figura 9: Configurare ObjectDataSource per supportare la memorizzazione nella cache usando le dipendenze della cache SQL in Products e Categories (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver configurato ObjectDataSource per supportare la memorizzazione nella cache, rivedere la pagina tramite un browser. Anche in questo caso, il testo 'Evento di selezione attivato' dovrebbe essere visualizzato alla prima visita della pagina, ma dovrebbe scomparire quando si effettua il passaggio di pagina, l'ordinamento o facendo clic sui pulsanti Modifica o Annulla. Ciò è dovuto al fatto che dopo che i dati vengono caricati nella cache di ObjectDataSource, rimangono lì finché le Products tabelle o Categories non vengono modificate o i dati vengono aggiornati tramite GridView.
Dopo aver sfogliato la griglia e aver notato la mancanza del testo 'Selecting event fired', aprire una nuova finestra del browser e navigare al tutorial di base nella sezione Modifica, Inserimento ed Eliminazione (~/EditInsertDelete/Basics.aspx). Aggiornare il nome o il prezzo di un prodotto. Quindi, dalla prima finestra del browser, visualizza una pagina diversa di dati, ordina la griglia o fai clic sul pulsante Modifica di una riga. Questa volta, l'evento di selezione generato dovrebbe essere nuovamente visualizzato, perché i dati del database sottostanti sono stati modificati (vedere la figura 10). Se il testo non viene visualizzato, attendere alcuni istanti e riprovare. Tenere presente che il servizio di polling verifica le modifiche apportate alla Products tabella ogni pollTime millisecondo, pertanto si verifica un ritardo tra l'aggiornamento dei dati sottostanti e la rimozione dei dati memorizzati nella cache.
Figura 10: Modifica della tabella Products rimuove i dati del prodotto memorizzati nella cache (fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 6: Utilizzo dellaSqlCacheDependencyclasse a livello di codice
L'esercitazione Caching dei dati nell'architettura ha esaminato i vantaggi dell'uso di un livello di caching separato nell'architettura anziché associare strettamente il caching con ObjectDataSource. In questa esercitazione è stata creata una ProductsCL classe per illustrare a livello di codice l'uso della cache dei dati. Per usare le dipendenze della cache SQL nel livello di caching, usare la classe SqlCacheDependency.
Con il sistema di polling, un SqlCacheDependency oggetto deve essere associato a una determinata coppia di database e tabelle. Il codice seguente, ad esempio, crea un SqlCacheDependency oggetto basato sulla tabella del Products database Northwind:
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
I due parametri di input per il SqlCacheDependency costruttore s sono rispettivamente i nomi di database e di tabella. Analogamente alla proprietà ObjectDataSource s SqlCacheDependency , il nome del database usato corrisponde al valore specificato nell'attributo dell'elemento name<add> in Web.config. Il nome della tabella è il nome effettivo della tabella di database.
Per associare un SqlCacheDependency a un elemento aggiunto alla cache dei dati, utilizzare uno degli overload di metodo Insert che accetta una dipendenza. Il codice seguente aggiunge valore alla cache dei dati per una durata illimitata, ma la associa a una SqlCacheDependency nella Products tabella. In breve, il valore rimarrà nella cache fino a quando non viene rimosso a causa di vincoli di memoria o perché il sistema di polling ha rilevato che la Products tabella è stata modificata dopo la memorizzazione nella cache.
Caching.SqlCacheDependency productsTableDependency =
new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key,
value,
productsTableDependency,
System.Web.Caching.Cache.NoAbsoluteExpiration,
System.Web.Caching.Cache.NoSlidingExpiration);
La classe del livello di cache ProductsCL attualmente memorizza nella cache i dati dalla tabella Products utilizzando una scadenza basata su tempo di 60 secondi. Aggiornare questa classe in modo che usi invece le dipendenze della cache SQL. Il ProductsCL metodo della AddCacheItem classe, responsabile dell'aggiunta dei dati alla cache, contiene attualmente il codice seguente:
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);
}
Aggiornare questo codice per usare un SqlCacheDependency oggetto anziché la dipendenza della MasterCacheKeyArray cache:
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);
}
Per testare la funzionalità, aggiungere un GridView alla pagina sotto il GridView esistente ProductsDeclarative. Imposta questo nuovo GridView su IDProductsProgrammatic e, usando il suo smart tag, collegalo a un nuovo ObjectDataSource denominato ProductsDataSourceProgrammatic. Configurare ObjectDataSource usando la classe ProductsCL, impostando rispettivamente gli elenchi a discesa nelle schede SELECT e UPDATE su GetProducts e UpdateProduct.
Figura 11: Configurare ObjectDataSource per l'uso della classe (ProductsCL a dimensione intera)
Figura 12: Scegliere il GetProducts metodo dalla lista delle schede SELECT Drop-Down (Fare clic per visualizzare l'immagine a grandezza naturale)
Figura 13: Scegliere il metodo UpdateProduct dalla scheda UPDATE Drop-Down List (fare clic per visualizzare l'immagine a dimensione intera)
Dopo aver completato la procedura guidata Configura origine dati, Visual Studio creerà BoundFields e CheckBoxFields in GridView per ognuno dei campi dati. Come per il primo GridView aggiunto a questa pagina, rimuovi tutti i campi, tranne ProductName, CategoryName e UnitPrice, e formatta questi campi nel modo desiderato. Dallo smart tag di GridView, selezionare le caselle di controllo Abilita paging, Abilita ordinamento e Abilita modifica. Come con ProductsDataSourceDeclarative ObjectDataSource, Visual Studio imposta la proprietà ProductsDataSourceProgrammatic di ObjectDataSource su OldValuesParameterFormatStringoriginal_{0}. Affinché la funzionalità di modifica di GridView funzioni correttamente, impostare nuovamente questa proprietà su {0} (o rimuovere completamente l'assegnazione di proprietà dalla sintassi dichiarativa).
Dopo aver completato queste attività, il markup dichiarativo GridView e ObjectDataSource risultante dovrebbe essere simile al seguente:
<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>
Per testare la dipendenza della cache SQL nel livello di memorizzazione nella cache, impostare un punto di interruzione nel ProductCL metodo della classe e AddCacheItem quindi avviare il debug. Quando si visita SqlCacheDependencies.aspxper la prima volta , il punto di interruzione deve essere raggiunto quando i dati vengono richiesti per la prima volta e inseriti nella cache. Passare quindi a un'altra pagina in GridView o ordinare una delle colonne. In questo modo GridView esegue nuovamente la query sui dati, ma i dati devono essere trovati nella cache perché la tabella di Products database non è stata modificata. Se i dati non sono stati trovati ripetutamente nella cache, assicurarsi che nel computer sia disponibile memoria sufficiente e riprovare.
Dopo aver sfogliato alcune pagine di GridView, aprire una seconda finestra del browser e passare all'esercitazione Basi nella sezione Modifica, inserimento ed eliminazione (~/EditInsertDelete/Basics.aspx). Aggiorna un record dalla tabella Prodotti e poi, dalla prima finestra del browser, visualizza una nuova pagina o clicca su una delle intestazioni di ordinamento.
In questo scenario verrà visualizzato uno dei due elementi seguenti: il punto di interruzione verrà raggiunto, a indicare che i dati memorizzati nella cache sono stati rimossi a causa della modifica nel database; oppure, il punto di interruzione non verrà raggiunto, vale a dire che SqlCacheDependencies.aspx ora mostra i dati non aggiornati. Se il punto di interruzione non viene raggiunto, è probabile che il servizio di polling non sia ancora stato attivato dopo la modifica dei dati. Tenere presente che il servizio di polling verifica le modifiche apportate alla Products tabella ogni pollTime millisecondo, pertanto si verifica un ritardo tra l'aggiornamento dei dati sottostanti e la rimozione dei dati memorizzati nella cache.
Annotazioni
Questo ritardo è più probabile quando si modifica uno dei prodotti tramite GridView in SqlCacheDependencies.aspx. Nell'esercitazione Memorizzazione dei dati nella cache dell'architettura abbiamo aggiunto la MasterCacheKeyArray dipendenza dalla cache per garantire che i dati modificati tramite il metodo della classe ProductsCLUpdateProduct fossero rimossi dalla cache. Tuttavia, questa dipendenza della cache è stata sostituita durante la modifica del AddCacheItem metodo precedente in questo passaggio e pertanto la ProductsCL classe continuerà a visualizzare i dati memorizzati nella cache fino a quando il sistema di polling non annota la modifica alla Products tabella. Si vedrà come reintrodurre la dipendenza della MasterCacheKeyArray cache nel passaggio 7.
Passaggio 7: Associazione di più dipendenze a un elemento memorizzato nella cache
Tenere presente che la MasterCacheKeyArray dipendenza della cache viene usata per garantire che tutti i dati correlati al prodotto vengano rimossi dalla cache quando viene aggiornato un singolo elemento associato. Ad esempio, il GetProductsByCategoryID(categoryID) metodo memorizza ProductsDataTables nella cache le istanze per ogni valore categoryID univoco. Se uno di questi oggetti viene rimosso, la dipendenza della MasterCacheKeyArray cache garantisce che anche le altre vengano rimosse. Senza questa dipendenza della cache, quando i dati memorizzati nella cache vengono modificati, esiste la possibilità che altri dati del prodotto memorizzati nella cache non siano aggiornati. Di conseguenza, è importante mantenere la dipendenza della MasterCacheKeyArray cache quando si usano le dipendenze della cache SQL. Tuttavia, il metodo s della Insert cache dei dati consente solo un singolo oggetto di dipendenza.
Inoltre, quando si usano le dipendenze della cache SQL, potrebbe essere necessario associare più tabelle di database come dipendenze. Ad esempio, la ProductsDataTable cache nella ProductsCL classe contiene i nomi di categoria e fornitore per ogni prodotto, ma il AddCacheItem metodo usa solo una dipendenza da Products. In questo caso, se l'utente aggiorna il nome di una categoria o di un fornitore, i dati del prodotto memorizzati nella cache rimarranno nella cache e non saranno aggiornati. Pertanto, si vuole rendere i dati del prodotto memorizzati nella cache dipendenti non solo dalla Products tabella, ma anche dalle Categories tabelle e Suppliers .
La AggregateCacheDependency classe fornisce un mezzo per associare più dipendenze a un elemento della cache. Per iniziare, creare un'istanza di AggregateCacheDependency. Aggiungere quindi il set di dipendenze usando il AggregateCacheDependency metodo s Add . Quando si inserisce l'elemento nella cache dei dati successivamente, passare l'istanza AggregateCacheDependency . Quando una delle dipendenze dell'istanza AggregateCacheDependency cambia, l'elemento memorizzato nella cache verrà rimosso.
Di seguito viene illustrato il codice aggiornato per la classe ProductsCL metodo s AddCacheItem. Il metodo crea la dipendenza della cache MasterCacheKeyArray così come gli oggetti SqlCacheDependency per le tabelle Products, Categories e Suppliers. Vengono tutti combinati in un AggregateCacheDependency oggetto denominato aggregateDependencies, che viene quindi passato al Insert metodo .
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);
}
Testare questo nuovo codice. Ora le modifiche apportate alle Productstabelle , Categorieso Suppliers causano la rimozione dei dati memorizzati nella cache. Inoltre, il ProductsCL metodo della UpdateProduct classe , che viene chiamato durante la modifica di un prodotto tramite GridView, rimuove la MasterCacheKeyArray dipendenza della cache, che causa la rimozione della cache ProductsDataTable e il recupero dei dati nella richiesta successiva.
Annotazioni
Le dipendenze della cache SQL possono essere usate anche con il caching dell'output. Per una dimostrazione di questa funzionalità, vedere Utilizzo della memorizzazione nella cache dell'output ASP.NET con SQL Server.
Riassunto
Quando si memorizzano nella cache i dati del database, i dati rimarranno idealmente nella cache fino a quando non verranno modificati nel database. Con ASP.NET 2.0, le dipendenze della cache SQL possono essere create e usate sia in scenari dichiarativi che programmatici. Una delle sfide di questo approccio consiste nell'individuare quando i dati sono stati modificati. Le versioni complete di Microsoft SQL Server 2005 offrono funzionalità di notifica che possono avvisare un'applicazione quando un risultato della query è stato modificato. Per l'edizione Express di SQL Server 2005 e le versioni precedenti di SQL Server, è necessario usare invece un sistema di polling. Fortunatamente, la configurazione dell'infrastruttura di polling necessaria è piuttosto semplice.
Buon programmatori!
Altre informazioni
Per altre informazioni sugli argomenti illustrati in questa esercitazione, vedere le risorse seguenti:
- Uso delle notifiche di query in Microsoft SQL Server 2005
- Creazione di una notifica di query
-
Memorizzazione nella cache in ASP.NET con la
SqlCacheDependencyclasse -
ASP.NET Strumento di registrazione di SQL Server (
aspnet_regsql.exe) -
Panoramica di
SqlCacheDependency
Informazioni sull'autore
Scott Mitchell, autore di sette libri ASP/ASP.NET e fondatore di 4GuysFromRolla.com, ha lavorato con le tecnologie Web Microsoft dal 1998. Scott lavora come consulente indipendente, formatore e scrittore. Il suo ultimo libro è Sams Teach Yourself ASP.NET 2.0 in 24 ore. Può essere raggiunto a mitchell@4GuysFromRolla.com.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori competenti. I revisori principali per questo tutorial erano Marko Rangel, Teresa Murphy e Hilton Giesenow. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, mandami un messaggio a mitchell@4GuysFromRolla.com.