Memorizzazione di dati nella cache all'avvio dell'applicazione (VB)

di Scott Mitchell

Scarica il PDF

In qualsiasi applicazione Web alcuni dati verranno usati di frequente e alcuni dati verranno usati raramente. È possibile migliorare le prestazioni dell'applicazione ASP.NET caricando in anticipo i dati usati di frequente, una tecnica nota come . Questa esercitazione illustra un approccio al caricamento proattivo, che consiste nel caricare i dati nella cache all'avvio dell'applicazione.

Introduzione

Le due esercitazioni precedenti hanno esaminato la memorizzazione dei dati nella cache nei livelli presentazione e memorizzazione nella cache. Nella memorizzazione nella cache dei dati con ObjectDataSource è stato esaminato l'uso delle funzionalità di memorizzazione nella cache di ObjectDataSource per memorizzare nella cache i dati nel livello presentazione. Memorizzazione nella cache dei dati nell'architettura esaminata nella memorizzazione nella cache in un nuovo livello di memorizzazione nella cache separato. Entrambe queste esercitazioni hanno usato il caricamento reattivo nell'uso della cache dei dati. Con il caricamento reattivo, ogni volta che vengono richiesti i dati, il sistema controlla innanzitutto se si trova nella cache. In caso contrario, recupera i dati dall'origine, ad esempio il database, e li archivia nella cache. Il vantaggio principale del caricamento reattivo è la facilità di implementazione. Uno dei suoi svantaggi è rappresentato da prestazioni non uniformi tra le richieste. Si supponga di usare il livello di memorizzazione nella cache dell'esercitazione precedente per visualizzare le informazioni sul prodotto. Quando questa pagina viene visitata per la prima volta o visitata per la prima volta dopo che i dati memorizzati nella cache sono stati rimossi a causa di vincoli di memoria o della scadenza specificata, i dati devono essere recuperati dal database. Di conseguenza, queste richieste di utenti richiederanno più tempo rispetto alle richieste degli utenti che possono essere gestite dalla cache.

Il caricamento proattivo offre una strategia alternativa di gestione della cache che semplifica le prestazioni tra le richieste caricando i dati memorizzati nella cache prima che siano necessari. In genere, il caricamento proattivo usa un processo che controlla periodicamente o riceve una notifica quando è stato eseguito un aggiornamento ai dati sottostanti. Questo processo aggiorna quindi la cache per mantenerla aggiornata. Il caricamento proattivo è particolarmente utile se i dati sottostanti provengono da una connessione di database lenta, un servizio Web o un'altra origine dati particolarmente lenta. Tuttavia, questo approccio al caricamento proattivo è più difficile da implementare, perché richiede la creazione, la gestione e la distribuzione di un processo per verificare la presenza di modifiche e aggiornare la cache.

Un altro tipo di caricamento proattivo e il tipo che verrà esaminato in questa esercitazione consiste nel caricare i dati nella cache all'avvio dell'applicazione. Questo approccio è particolarmente utile per la memorizzazione nella cache dei dati statici, ad esempio i record nelle tabelle di ricerca del database.

Nota

Per un'analisi più approfondita delle differenze tra caricamento proattivo e reattivo, nonché elenchi di pro, svantaggi e raccomandazioni sull'implementazione, vedere la sezione Gestione del contenuto di una cache della Guida all'architettura di memorizzazione nella cache per le applicazioni .NET Framework.

Passaggio 1: Determinazione dei dati da memorizzare nella cache all'avvio dell'applicazione

Gli esempi di memorizzazione nella cache che usano il caricamento reattivo esaminato nelle due esercitazioni precedenti funzionano bene con i dati che possono cambiare periodicamente e non richiedono molto tempo per generare. Tuttavia, se i dati memorizzati nella cache non cambiano mai, la scadenza usata dal caricamento reattivo è superflua. Analogamente, se i dati memorizzati nella cache richiedono molto tempo per la generazione, gli utenti le cui richieste trovano la cache vuota dovranno sopportare un lungo attesa mentre i dati sottostanti vengono recuperati. Prendere in considerazione la memorizzazione nella cache di dati e dati statici che richiedono un tempo estremamente lungo per generare all'avvio dell'applicazione.

Anche se i database hanno molti valori dinamici e a modifica frequente, la maggior parte ha anche una quantità equa di dati statici. Ad esempio, praticamente tutti i modelli di dati hanno una o più colonne che contengono un determinato valore da un set fisso di scelte. Una Patients tabella di database può avere una PrimaryLanguage colonna il cui set di valori può essere inglese, spagnolo, francese, russo, giapponese e così via. Spesso, questi tipi di colonne vengono implementati usando le tabelle di ricerca. Invece di archiviare la stringa inglese o francese nella Patients tabella, viene creata una seconda tabella che contiene, in genere, due colonne, un identificatore univoco e una descrizione stringa, con un record per ogni valore possibile. La PrimaryLanguage colonna nella Patients tabella archivia l'identificatore univoco corrispondente nella tabella di ricerca. Nella figura 1, la lingua primaria di John Doe è inglese, mentre Ed Johnson è russo.

La tabella Languages è una tabella di ricerca utilizzata dalla tabella pazienti

Figura 1: La Languages tabella è una tabella di ricerca usata dalla Patients tabella

L'interfaccia utente per la modifica o la creazione di un nuovo paziente include un elenco a discesa di lingue consentite popolate dai record nella Languages tabella. Senza memorizzazione nella cache, ogni volta che questa interfaccia viene visitata, il sistema deve eseguire una query sulla Languages tabella. Questo è sprecato e non necessario poiché i valori della tabella di ricerca cambiano molto raramente, se mai.

È possibile memorizzare nella cache i Languages dati usando le stesse tecniche di caricamento reattive esaminate nelle esercitazioni precedenti. Il caricamento reattivo, tuttavia, usa una scadenza basata sul tempo, che non è necessaria per i dati della tabella di ricerca statica. Anche se la memorizzazione nella cache tramite caricamento reattivo sarebbe migliore di nessuna memorizzazione nella cache, l'approccio migliore consiste nel caricare in modo proattivo i dati della tabella di ricerca nella cache all'avvio dell'applicazione.

In questa esercitazione verrà illustrato come memorizzare nella cache i dati della tabella di ricerca e altre informazioni statiche.

Passaggio 2: Esame dei diversi modi per memorizzare nella cache i dati

Le informazioni possono essere memorizzate nella cache a livello di codice in un'applicazione ASP.NET usando un'ampia gamma di approcci. Abbiamo già visto come usare la cache dei dati nelle esercitazioni precedenti. In alternativa, gli oggetti possono essere memorizzati nella cache a livello di codice usando membri statici o stato dell'applicazione.

Quando si lavora con una classe, in genere è necessario creare un'istanza della classe prima di poter accedere ai relativi membri. Ad esempio, per richiamare un metodo da una delle classi nel livello della logica di business, è prima necessario creare un'istanza della classe :

Dim productsAPI As New ProductsBLL()
productsAPI.SomeMethod()
productsAPI.SomeProperty = "Hello, World!"

Prima di poter richiamare SomeMethod o lavorare con SomeProperty, è prima necessario creare un'istanza della classe usando la New parola chiave . SomeMethod e SomeProperty sono associati a una determinata istanza. La durata di questi membri è associata alla durata dell'oggetto associato. I membri statici, d'altra parte, sono variabili, proprietà e metodi condivisi tra tutte le istanze della classe e, di conseguenza, hanno una durata fino alla classe . I membri statici sono indicati dalla parola chiave Shared.

Oltre ai membri statici, i dati possono essere memorizzati nella cache usando lo stato dell'applicazione. Ogni applicazione ASP.NET gestisce una raccolta nome/valore condivisa tra tutti gli utenti e le pagine dell'applicazione. È possibile accedere a questa raccolta usando la HttpContext proprietà della Applicationclasse e usata da una classe code-behind della pagina ASP.NET, come illustrato di seguito:

Application("key") = value
Dim value As Object = Application("key")

La cache dei dati offre un'API molto più ricca per la memorizzazione nella cache dei dati, fornendo meccanismi per le scadenze basate su tempo e dipendenze, priorità degli elementi della cache e così via. Con i membri statici e lo stato dell'applicazione, tali funzionalità devono essere aggiunte manualmente dallo sviluppatore della pagina. Quando si memorizzano nella cache i dati all'avvio dell'applicazione per la durata dell'applicazione, tuttavia, i vantaggi della cache dei dati sono i seguenti. In questa esercitazione si esaminerà il codice che usa tutte e tre le tecniche per la memorizzazione nella cache dei dati statici.

Passaggio 3: Memorizzazione nella cache dei dati dellaSupplierstabella

Le tabelle di database Northwind implementate finora non includono tabelle di ricerca tradizionali. Le quattro tabelle DataTable implementate in DAL sono tutte le tabelle del modello i cui valori non sono statici. Invece di dedicare il tempo necessario per aggiungere una nuova tabella DataTable a DAL e quindi a una nuova classe e metodi al BLL, per questa esercitazione è sufficiente fingere che i Suppliers dati della tabella siano statici. Di conseguenza, è possibile memorizzare questi dati nella cache all'avvio dell'applicazione.

Per iniziare, creare una nuova classe denominata StaticCache.cs nella CL cartella .

Creare la classe StaticCache.vb nella cartella CL

Figura 2: Creare la StaticCache.vb classe nella CL cartella

È necessario aggiungere un metodo che carica i dati all'avvio nell'archivio cache appropriato, nonché metodi che restituiscono dati da questa cache.

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Private Shared suppliers As Northwind.SuppliersDataTable = Nothing
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using a static member variable
        Dim suppliersBLL As New SuppliersBLL()
        suppliers = suppliersBLL.GetSuppliers()
    End Sub
    
    <DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return suppliers
    End Function
End Class

Il codice precedente usa una variabile membro statica, suppliers, per contenere i risultati del SuppliersBLL metodo della GetSuppliers() classe , che viene chiamato dal LoadStaticCache() metodo . Il LoadStaticCache() metodo deve essere chiamato durante l'avvio dell'applicazione. Dopo aver caricato questi dati all'avvio dell'applicazione, qualsiasi pagina che deve usare i dati del fornitore può chiamare il StaticCache metodo della GetSuppliers() classe . Pertanto, la chiamata al database per ottenere i fornitori avviene una sola volta, all'avvio dell'applicazione.

Invece di usare una variabile membro statica come archivio cache, è possibile usare in alternativa lo stato dell'applicazione o la cache dei dati. Il codice seguente mostra la classe riorganizzata per usare lo stato dell'applicazione:

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using application state
        Dim suppliersBLL As New SuppliersBLL()
        HttpContext.Current.Application("key") = suppliers
    End Sub
    
    <DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return TryCast(HttpContext.Current.Application("key"), _
            Northwind.SuppliersDataTable)
    End Function
End Class

In LoadStaticCache()le informazioni sul fornitore vengono archiviate nella chiave della variabile dell'applicazione. Viene restituito come tipo appropriato (Northwind.SuppliersDataTable) da GetSuppliers(). Anche se è possibile accedere allo stato dell'applicazione nelle classi code-behind di ASP.NET pagine usando Application("key"), nell'architettura è necessario usare HttpContext.Current.Application("key") per ottenere l'oggetto corrente HttpContext.

Analogamente, la cache dei dati può essere usata come archivio cache, come illustrato nel codice seguente:

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using a static member variable
        Dim suppliersBLL As New SuppliersBLL()
        HttpRuntime.Cache.Insert("key", suppliers, Nothing, _
            Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, _
            CacheItemPriority.NotRemovable, Nothing)
    End Sub
    <System.ComponentModel.DataObjectMethodAttribute_
    (System.ComponentModel.DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return TryCast(HttpRuntime.Cache("key"), Northwind.SuppliersDataTable)
    End Function
End Class

Per aggiungere un elemento alla cache dei dati senza scadenza basata sul tempo, usare i System.Web.Caching.Cache.NoAbsoluteExpiration valori e System.Web.Caching.Cache.NoSlidingExpiration come parametri di input. Questo particolare overload del metodo della Insert cache dei dati è stato selezionato in modo da poter specificare la priorità dell'elemento della cache. La priorità viene usata per determinare gli elementi da scavengere dalla cache quando la memoria disponibile è insufficiente. In questo caso viene usata la priorità NotRemovable, che garantisce che questo elemento della cache non venga scavenged.

Nota

Questo download dell'esercitazione implementa la StaticCache classe usando l'approccio della variabile membro statica. Il codice per le tecniche relative allo stato dell'applicazione e alla cache dei dati è disponibile nei commenti nel file di classe.

Passaggio 4: Esecuzione del codice all'avvio dell'applicazione

Per eseguire il codice all'avvio di un'applicazione Web, è necessario creare un file speciale denominato Global.asax. Questo file può contenere gestori eventi per gli eventi a livello di applicazione, sessione e richiesta ed è qui che è possibile aggiungere codice che verrà eseguito ogni volta che viene avviata l'applicazione.

Aggiungere il Global.asax file alla directory radice dell'applicazione Web facendo clic con il pulsante destro del mouse sul nome del progetto del sito Web in Visual Studio Esplora soluzioni e scegliendo Aggiungi nuovo elemento. Nella finestra di dialogo Aggiungi nuovo elemento selezionare il tipo di elemento Classe applicazione globale e quindi fare clic sul pulsante Aggiungi.

Nota

Se nel progetto è già presente un Global.asax file, il tipo di elemento Classe applicazione globale non verrà elencato nella finestra di dialogo Aggiungi nuovo elemento.

Aggiungere il file Global.asax alla directory radice dell'applicazione Web

Figura 3: Aggiungere il Global.asax file alla directory radice dell'applicazione Web (fare clic per visualizzare l'immagine a dimensione intera)

Il modello di file predefinito Global.asax include cinque metodi all'interno di un tag lato <script> server:

  • Application_Start viene eseguito al primo avvio dell'applicazione Web
  • Application_End viene eseguito quando l'applicazione viene arrestata
  • Application_Error viene eseguito ogni volta che un'eccezione non gestita raggiunge l'applicazione
  • Session_Start viene eseguito quando viene creata una nuova sessione
  • Session_End viene eseguito quando una sessione è scaduta o abbandonata

Il Application_Start gestore eventi viene chiamato una sola volta durante il ciclo di vita di un'applicazione. L'applicazione avvia la prima volta che viene richiesta una risorsa ASP.NET dall'applicazione e continua a essere eseguita fino al riavvio dell'applicazione, che può verificarsi modificando il contenuto della /Bin cartella, modificando , modificando Global.asaxil contenuto nella App_Code cartella o modificando il Web.config file, tra le altre cause. Per una discussione più dettagliata sul ciclo di vita dell'applicazione, vedere ASP.NET Panoramica del ciclo di vita dell'applicazione.

Per queste esercitazioni è sufficiente aggiungere codice al Application_Start metodo, quindi è possibile rimuovere gli altri. In Application_Startè sufficiente chiamare il StaticCache metodo della LoadStaticCache() classe , che caricherà e memorizza nella cache le informazioni sul fornitore:

<%@ Application Language="VB" %>
<script runat="server">
    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        StaticCache.LoadStaticCache()
    End Sub
</script>

Questo è tutto lì! All'avvio dell'applicazione, il LoadStaticCache() metodo afferra le informazioni sul fornitore dal BLL e lo archivia in una variabile membro statica (o in qualsiasi archivio cache usato nella StaticCache classe ). Per verificare questo comportamento, impostare un punto di interruzione nel Application_Start metodo ed eseguire l'applicazione. Si noti che il punto di interruzione viene raggiunto all'avvio dell'applicazione. Le richieste successive, tuttavia, non causano l'esecuzione del Application_Start metodo.

Usare un punto di interruzione per verificare che sia in corso l'esecuzione del gestore eventi Application_Start

Figura 4: Usare un punto di interruzione per verificare che il Application_Start gestore eventi sia in esecuzione (fare clic per visualizzare l'immagine a dimensione intera)

Nota

Se non si raggiunge il punto di interruzione al primo avvio del Application_Start debug, è perché l'applicazione è già stata avviata. Forzare il riavvio dell'applicazione modificando i Global.asax file o Web.config e quindi riprovare. È sufficiente aggiungere (o rimuovere) una riga vuota alla fine di uno di questi file per riavviare rapidamente l'applicazione.

Passaggio 5: Visualizzazione dei dati memorizzati nella cache

A questo punto la StaticCache classe ha una versione dei dati del fornitore memorizzati nella cache all'avvio dell'applicazione a cui è possibile accedere tramite il relativo GetSuppliers() metodo. Per usare questi dati dal livello presentazione, è possibile usare ObjectDataSource o richiamare a livello di codice il StaticCache metodo della GetSuppliers() classe da una classe code-behind della pagina ASP.NET. Esaminiamo l'uso dei controlli ObjectDataSource e GridView per visualizzare le informazioni sui fornitori memorizzate nella cache.

Per iniziare, aprire la AtApplicationStartup.aspx pagina nella Caching cartella . Trascinare un controllo GridView dalla casella degli strumenti nella finestra di progettazione, impostandone la ID proprietà su Suppliers. Successivamente, dallo smart tag di GridView scegliere di creare un nuovo ObjectDataSource denominato SuppliersCachedDataSource. Configurare ObjectDataSource per l'uso del StaticCache metodo della GetSuppliers() classe .

Configurare ObjectDataSource per l'uso della classe StaticCache

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

Utilizzare il metodo GetSuppliers() per recuperare i dati dei fornitori memorizzati nella cache

Figura 6: Usare il GetSuppliers() metodo per recuperare i dati dei fornitori memorizzati nella cache (fare clic per visualizzare l'immagine a dimensione intera)

Al termine della procedura guidata, Visual Studio aggiungerà automaticamente BoundFields per ognuno dei campi dati in SuppliersDataTable. Il markup dichiarativo di GridView e ObjectDataSource dovrebbe essere simile al seguente:

<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="SupplierID" DataSourceID="SuppliersCachedDataSource" 
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="SupplierID" HeaderText="SupplierID" 
            InsertVisible="False" ReadOnly="True" 
            SortExpression="SupplierID" />
        <asp:BoundField DataField="CompanyName" HeaderText="CompanyName" 
            SortExpression="CompanyName" />
        <asp:BoundField DataField="Address" HeaderText="Address" 
            SortExpression="Address" />
        <asp:BoundField DataField="City" HeaderText="City" 
            SortExpression="City" />
        <asp:BoundField DataField="Country" HeaderText="Country" 
            SortExpression="Country" />
        <asp:BoundField DataField="Phone" HeaderText="Phone" 
            SortExpression="Phone" />
    </Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersCachedDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="StaticCache" />

La figura 7 mostra la pagina visualizzata tramite un browser. L'output è lo stesso che è stato eseguito il pull dei dati dalla classe BLL, SuppliersBLL ma l'uso della StaticCache classe restituisce i dati del fornitore memorizzati nella cache all'avvio dell'applicazione. È possibile impostare punti di interruzione nel StaticCache metodo della GetSuppliers() classe per verificare questo comportamento.

I dati dei fornitori memorizzati nella cache vengono visualizzati in un controllo GridView

Figura 7: I dati dei fornitori memorizzati nella cache vengono visualizzati in un controllo GridView (fare clic per visualizzare un'immagine a dimensione intera)

Riepilogo

La maggior parte di ogni modello di dati contiene una quantità equa di dati statici, in genere implementata sotto forma di tabelle di ricerca. Poiché queste informazioni sono statiche, non esiste alcun motivo per accedere continuamente al database ogni volta che queste informazioni devono essere visualizzate. Inoltre, a causa della sua natura statica, quando si memorizzano nella cache i dati non sono necessari per una scadenza. In questa esercitazione è stato illustrato come accettare tali dati e memorizzarlo nella cache dei dati, nello stato dell'applicazione e tramite una variabile membro statica. Queste informazioni vengono memorizzate nella cache all'avvio dell'applicazione e rimangono nella cache per tutta la durata dell'applicazione.

In questa esercitazione e nelle ultime due sono stati esaminati i dati di memorizzazione nella cache per la durata dell'applicazione e l'uso delle scadenze basate sul tempo. Quando si memorizzano nella cache i dati del database, tuttavia, una scadenza basata sul tempo può essere inferiore all'ideale. Anziché scaricare periodicamente la cache, sarebbe consigliabile rimuovere solo l'elemento memorizzato nella cache quando i dati del database sottostanti vengono modificati. Questa soluzione ideale è possibile tramite l'uso delle dipendenze della cache SQL, che verranno esaminate nell'esercitazione successiva.

Buon programmatori!

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 per questa esercitazione sono stati Teresa Murphy e Zack Jones. Si è interessati a esaminare i prossimi articoli MSDN? In tal caso, rilasciami una riga in mitchell@4GuysFromRolla.com.