Uso delle dipendenze della cache SQL (VB)
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 significa che i dati memorizzati nella cache non mantengono alcuna associazione con l'origine dati sottostante, generando dati non aggiornati che vengono mantenuti troppo lunghi o dati correnti scaduti 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 dati di memorizzazione nella cache con ObjectDataSource e Memorizzazione nella cache dei dati nelle esercitazioni sull'architettura hanno usato 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 delle prestazioni della memorizzazione nella cache solo per 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 vengono 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 e rimuove 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, verrà creata l'infrastruttura necessaria per supportare il polling e quindi si esaminerà come usare la SqlCacheDependency
classe in scenari dichiarativi e programmatici.
Informazioni su notifica e polling
Esistono due tecniche che è possibile usare 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 dall'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 informazioni su quando sono state aggiornate tabelle specifiche. 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 gli elementi della cache associati rimossi.
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 concentreremo sulla configurazione e sull'uso dell'opzione di polling. Consultare 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
, notificationCreated
e 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 incrementata il valore della changeId
tabella in AspNet_SqlCacheTablesForChangeNotification
.
Il runtime ASP.NET tiene traccia dell'oggetto corrente changeId
per una tabella durante la memorizzazione nella cache dei dati tramite un SqlCacheDependency
oggetto . Il database viene controllato periodicamente e tutti gli SqlCacheDependency
oggetti i cui changeId
oggetti differiscono dal valore nel database vengono rimossi poiché 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.exe
riga di comando
Con l'approccio di polling il database deve essere configurato per contenere l'infrastruttura descritta in precedenza: una tabella predefinita (AspNet_SqlCacheTablesForChangeNotification
), una manciata di stored procedure e trigger in ognuna delle tabelle che possono essere usate nelle dipendenze della cache SQL nell'applicazione Web. Queste tabelle, stored procedure e trigger possono essere creati tramite il programma aspnet_regsql.exe
della riga di comando , disponibile nella $WINDOWS$\Microsoft.NET\Framework\version
cartella . 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
Nota
Per eseguire questi comandi, l'account di accesso al db_securityadmin
database specificato deve trovarsi nei ruoli 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
tramite l'autenticazione di Windows, passare alla directory appropriata e, dalla riga di comando, immettere:
aspnet_regsql.exe -S ScottsServer -E -d pubs -ed
Dopo aver aggiunto l'infrastruttura a livello di database, è necessario aggiungere i trigger a tali 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 authors
tabelle e titles
nel pubs
database in 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 questa esercitazione aggiungere i trigger alle Products
tabelle , Categories
e Suppliers
. Si esaminerà la sintassi della riga di comando specifica nel passaggio 3.
Passaggio 2: Riferimento a un database di 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 si trova nella App_Data
cartella? Invece di dover individuare i nomi di database e server, è stato rilevato 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 ha solo l'edizione Express, è possibile scaricare il SQL Server Management Studio Microsoft gratuito.
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 includerà 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 in 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 in un altro nome Human-Friendly
Passaggio 3: Aggiunta dell'infrastruttura di polling al database Northwind
Dopo aver collegato il NORTHWND.MDF
database dalla App_Data
cartella, è possibile 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 la riapertura di Visual Studio, esaminare il database tramite Esplora server. Si noti la nuova tabella (AspNet_SqlCacheTablesForChangeNotification
), le nuove stored procedure e i trigger nelle Products
tabelle , 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 esegue il polling del database Northwind una volta al 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 leggibile a un database specifico. 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
stored procedure. Questa stored procedure, aggiunta al passaggio 3 usando lo strumento da aspnet_regsql.exe
riga di comando, restituisce i tableName
valori 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 più rapidamente rimuove i dati obsoleti dalla cache. Un valore maggiore pollTime
riduce il numero di richieste di database, ma aumenta il ritardo tra quando i dati back-end cambiano e quando vengono rimossi gli elementi della cache correlati. Fortunatamente, la richiesta di database esegue una stored procedure semplice che restituisce solo poche righe da una semplice tabella leggera. Provare tuttavia a usare valori diversi pollTime
per trovare un equilibrio ideale tra l'accesso al database e l'decadimento dei dati per l'applicazione. Il valore più pollTime
piccolo consentito è 500.
Nota
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 programmatiche o dichiarative. In questo passaggio si esaminerà come usare in modo dichiarativo le dipendenze della cache SQL. Nel passaggio 6 verrà esaminato l'approccio programmatico.
L'esercitazione Memorizzazione nella cache dei dati con ObjectDataSource ha esaminato le funzionalità di memorizzazione nella cache dichiarativa di 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 gridView dalla casella degli strumenti nella Designer. Impostare GridView su ID
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
, unitPrice
e productID
. Impostare gli elenchi a discesa su (Nessuno) nelle schede INSERT e DELETE.
Figura 6: Usare l'overload updateProduct con tre parametri di input (fare clic per visualizzare l'immagine a dimensione intera)
Figura 7: Impostare l'elenco 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
, CategoryName
e UnitPrice
, e formattare questi campi in base alle esigenze. Dallo smart tag gridView selezionare le caselle di controllo Abilita paging, Abilita ordinamento e Abilita modifica. Visual Studio imposterà la proprietà original_{0}
ObjectDataSource su OldValuesParameterFormatString
. Affinché la funzionalità di modifica di GridView funzioni correttamente, rimuovere completamente questa proprietà dalla sintassi dichiarativa o impostarla nuovamente sul valore predefinito, {0}
.
Aggiungere infine un controllo Web Etichetta 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 illustrare 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 e Selecting
aggiungere il codice seguente:
Protected Sub ProductsDataSourceDeclarative_Selecting _
(sender As Object, e As ObjectDataSourceSelectingEventArgs) _
Handles ProductsDataSourceDeclarative.Selecting
ODSEvents.Text = "-- Selecting event fired"
End Sub
Tenere presente che l'evento ObjectDataSource viene Selecting
generato solo durante il recupero dei 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é è ancora stato implementato qualsiasi memorizzazione nella cache, ogni volta che si esegue l'ordinamento, l'ordinamento o la griglia nella griglia verrà visualizzato il testo "Selezione dell'evento generato, come illustrato nella figura 8.
Figura 8: L'evento ObjectDataSource viene Selecting
generato ogni volta che GridView viene sottoposto a paging, modificato o ordinato (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 nella cache i dati per la durata specificata dalla relativa CacheDuration
proprietà. ObjectDataSource include anche 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.config
e tableName è il nome della tabella di database. Ad esempio, per creare un ObjectDataSource che memorizza nella cache i dati a tempo indefinito in base a una dipendenza della cache SQL dalla tabella NorthwindProducts
, impostare la proprietà True
ObjectDataSource su EnableCaching
e la relativa SqlCacheDependency
proprietà su NorthwindDB:Products.
Nota
È possibile usare una dipendenza della cache SQL e una scadenza basata sul tempo impostando EnableCaching
True
su , CacheDuration
sull'intervallo di tempo e SqlCacheDependency
sui nomi del database e della tabella. ObjectDataSource rimuoverà 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 di due tabelle e Products
Categories
(il campo del CategoryName
prodotto viene recuperato tramite un oggetto JOIN
su Categories
). Si vogliono quindi 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 'Selezione evento generato dovrebbe essere visualizzato nella prima pagina visita, ma dovrebbe andare via durante il paging, l'ordinamento o facendo clic sui pulsanti Modifica o Annulla. Ciò è dovuto al fatto che dopo il caricamento dei dati nella cache objectDataSource rimane presente fino a quando le Products
tabelle o Categories
non vengono modificate o i dati vengono aggiornati tramite GridView.
Dopo aver eseguito il paging nella griglia e aver notato la mancanza del testo generato dall'evento di selezione, aprire una nuova finestra del browser e passare all'esercitazione Informazioni 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, visualizzare una pagina diversa di dati, ordinare la griglia o fare 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 controlla 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: La modifica della tabella Products rimuove i dati del prodotto memorizzati nella cache (fare clic per visualizzare l'immagine a dimensione intera)
Passaggio 6: Utilizzo dellaSqlCacheDependency
classe a livello di codice
L'esercitazione Memorizzazione nella cache dei dati nell'architettura ha esaminato i vantaggi dell'uso di un livello di memorizzazione nella cache separato nell'architettura anziché associare strettamente la memorizzazione nella cache 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 memorizzazione nella cache, usare la SqlCacheDependency
classe .
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:
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
I due parametri di input per il SqlCacheDependency
costruttore s sono rispettivamente i nomi di database e tabella. Analogamente alla proprietà ObjectDataSource, 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 oggetto a un SqlCacheDependency
elemento aggiunto alla cache dei dati, usare uno degli overload del Insert
metodo che accetta una dipendenza. Il codice seguente aggiunge valore alla cache dei dati per una durata indefinita, ma la associa a una SqlCacheDependency
nella Products
tabella. In breve, il valore rimarrà nella cache finché 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.
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Cache.Insert(key, _
value, _
productsTableDependency, _
System.Web.Caching.Cache.NoAbsoluteExpiration, _
System.Web.Caching.Cache.NoSlidingExpiration)
La classe Caching Layer attualmente ProductsCL
memorizza nella cache i dati della Products
tabella usando una scadenza basata sul 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 Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it
If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
DataCache(MasterCacheKeyArray(0)) = DateTime.Now
End If
' Add a CacheDependency
Dim dependency As _
New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
DataCache.Insert(GetCacheKey(rawKey), value, dependency, _
DateTime.Now.AddSeconds(CacheDuration), _
Caching.Cache.NoSlidingExpiration)
End Sub
Aggiornare questo codice per usare un SqlCacheDependency
oggetto anziché la dipendenza della MasterCacheKeyArray
cache:
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Add the SqlCacheDependency objects for Products
Dim productsTableDependency As New _
Caching.SqlCacheDependency("NorthwindDB", "Products")
DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency, _
Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub
Per testare questa funzionalità, aggiungere un controllo GridView alla pagina sotto il controllo GridView esistente ProductsDeclarative
. Impostare questo nuovo oggetto GridView su ID
ProductsProgrammatic
e, tramite il relativo smart tag, associarlo a un nuovo ObjectDataSource denominato ProductsDataSourceProgrammatic
. Configurare ObjectDataSource per l'uso della ProductsCL
classe , impostando rispettivamente gli elenchi a discesa nelle schede GetProducts
SELECT e UPDATE su e UpdateProduct
.
Figura 11: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagineProductsCL
a dimensione intera)
Figura 12: Selezionare il GetProducts
metodo dall'elenco select tab Drop-Down (fare clic per visualizzare l'immagine a dimensione intera)
Figura 13: Scegliere il metodo UpdateProduct dall'elenco Drop-Down scheda UPDATE (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 controllo GridView aggiunto a questa pagina, rimuovere tutti i campi, ma ProductName
, CategoryName
e UnitPrice
, e formattare questi campi in base alle esigenze. Dallo smart tag gridView selezionare le caselle di controllo Abilita paging, Abilita ordinamento e Abilita modifica. Come per ProductsDataSourceDeclarative
ObjectDataSource, Visual Studio imposterà la ProductsDataSourceProgrammatic
proprietà original_{0}
ObjectDataSource su OldValuesParameterFormatString
. 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 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.aspx
per 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 Products
tabella di 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 eseguito il paging in alcune pagine di GridView, aprire una seconda finestra del browser e passare all'esercitazione Informazioni di base nella sezione Modifica, inserimento ed eliminazione (~/EditInsertDelete/Basics.aspx
). Aggiornare un record dalla tabella Products e quindi, dalla prima finestra del browser, visualizzare una nuova pagina o fare clic su una delle intestazioni di ordinamento.
In questo scenario verrà visualizzato uno dei due elementi seguenti: verrà raggiunto il punto di interruzione, 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, ovvero SqlCacheDependencies.aspx
ora visualizza 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 controlla 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.
Nota
Questo ritardo è più probabile che venga visualizzato quando si modifica uno dei prodotti tramite GridView in SqlCacheDependencies.aspx
. Nell'esercitazione Memorizzazione nella cache dei dati nell'architettura è stata aggiunta la dipendenza della MasterCacheKeyArray
cache per assicurarsi che i dati modificati tramite il ProductsCL
metodo della UpdateProduct
classe siano stati rimossi dalla cache. Tuttavia, questa dipendenza della cache è stata sostituita quando si modifica il AddCacheItem
metodo in precedenza in questo passaggio e pertanto la ProductsCL
classe continuerà a visualizzare i dati memorizzati nella cache finché il sistema di polling non annota la modifica alla Products
tabella. Verrà illustrato 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 dipendenza della MasterCacheKeyArray
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 nella cache le ProductsDataTables
istanze per ogni valore categoryID univoco. Se uno di questi oggetti viene rimosso, la dipendenza della MasterCacheKeyArray
cache garantisce che vengano rimosse anche le altre. 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 della cache dei Insert
dati consente solo un singolo oggetto 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 AggregateCacheDependency
di . 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 il ProductsCL
metodo della AddCacheItem
classe . Il metodo crea la dipendenza della MasterCacheKeyArray
cache insieme agli SqlCacheDependency
oggetti per le Products
tabelle , Categories
e Suppliers
. Vengono tutti combinati in un AggregateCacheDependency
oggetto denominato aggregateDependencies
, che viene quindi passato al Insert
metodo .
Private Sub AddCacheItem(ByVal rawKey As String, ByVal value As Object)
Dim DataCache As System.Web.Caching.Cache = HttpRuntime.Cache
' Make sure MasterCacheKeyArray(0) is in the cache - if not, add it.
If DataCache(MasterCacheKeyArray(0)) Is Nothing Then
DataCache(MasterCacheKeyArray(0)) = DateTime.Now
End If
'Create the CacheDependency
Dim masterCacheKeyDependency As _
New Caching.CacheDependency(Nothing, MasterCacheKeyArray)
' Add the SqlCacheDependency objects for Products, Categories, and Suppliers
Dim productsTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Products")
Dim categoriesTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Categories")
Dim suppliersTableDependency As _
New Caching.SqlCacheDependency("NorthwindDB", "Suppliers")
' Create an AggregateCacheDependency
Dim aggregateDependencies As New Caching.AggregateCacheDependency()
aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency, _
categoriesTableDependency, suppliersTableDependency)
DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies, _
Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration)
End Sub
Testare questo nuovo codice. Le modifiche apportate alle Products
tabelle , Categories
o 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 dipendenza della MasterCacheKeyArray
cache, che causa la rimozione della cache ProductsDataTable
e il recupero dei dati nella richiesta successiva.
Nota
Le dipendenze della cache SQL possono essere usate anche con la memorizzazione nella cache dell'output. Per una dimostrazione di questa funzionalità, vedere Uso della memorizzazione nella cache di output ASP.NET con SQL Server.
Riepilogo
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 in scenari dichiarativi e programmatici. Una delle sfide con 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 è cambiato. Per Express Edition di SQL Server 2005 e 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 descritti 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
SqlCacheDependency
classe - strumento di registrazione ASP.NET 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, lavora 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 all'indirizzo mitchell@4GuysFromRolla.com. o tramite il suo blog, disponibile all'indirizzo http://ScottOnWriting.NET.
Grazie speciale a
Questa serie di esercitazioni è stata esaminata da molti revisori utili. I revisori principali di questa esercitazione erano Marko Rangel, Teresa Murphy e Hilton Giesenow. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.