Uso delle dipendenze della cache SQL (VB)

di Scott Mitchell

Scarica il PDF

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, 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 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.exeriga 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.exedella 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 Productstabelle , Categoriese 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.

Connettersi a localhost\SQLExpress Server

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.

Collegare NORTHWND. Database MDF dalla cartella App_Data

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.

Rinominare il database collegato in un altro nome Human-Friendly

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 Productstabelle , Categoriese Suppliers .

Il database include ora l'infrastruttura di polling necessaria

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 IDProductsDeclarative e, dallo smart tag, scegliere di associarlo a un nuovo ObjectDataSource denominato ProductsDataSourceDeclarative.

Creare 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 updateProduct con tre parametri di input (fare clic per visualizzare l'immagine a dimensione intera)

Impostare l'elenco Drop-Down su (Nessuno) per le schede INSERT e DELETE

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, CategoryNamee 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.

L'evento Di selezione di ObjectDataSource viene generato ogni volta che GridView viene sottoposto a paging, modificato o ordinato

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.confige 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 EnableCachingTruesu , 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 ProductsCategories (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 .

Configurare ObjectDataSource per supportare la memorizzazione nella cache tramite dipendenze della cache SQL in prodotti e categorie

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.

La modifica della tabella Products rimuove i dati del prodotto 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 dellaSqlCacheDependencyclasse 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 IDProductsProgrammatic 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.

Configurare ObjectDataSource per l'uso della classe ProductsCL

Figura 11: Configurare ObjectDataSource per l'uso della classe (fare clic per visualizzare l'immagineProductsCL a dimensione intera)

Selezionare il metodo GetProducts dall'elenco di Drop-Down della scheda SELECT

Figura 12: Selezionare il GetProducts metodo dall'elenco select tab Drop-Down (fare clic per visualizzare l'immagine a dimensione intera)

Scegliere il metodo UpdateProduct dall'elenco Drop-Down scheda UPDATE

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, CategoryNamee 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.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 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 Productstabelle , Categoriese 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 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 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:

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.