asp - asp.net - aspcode.it

COMMUNITY - Login
 Username:
 
 Password:
 
Voglio registrarmi!
Password dimenticata?
 Utenti on-line: 0
 Ospiti on-line: 7999
ASPCode.it - Store

  > > Articoli

Caching in ASP.net (2/2) - Il caching programmatico

Data di pubblicazione: 05/12/2006        Voto della community: 4,85 (Votanti: 9)

Oltre al Caching dell'output, ASP.NET mette a disposizione degli sviluppatori un altro strumento molto potente per memorizzare dati e oggetti nella Cache in sede di programmazione: la classe Cache. Ogni volta che viene avviata un'applicazione ASP.NET, il Framework crea un'istanza privata di questa classe, che rimane attiva fino a quando l'applicazione stessa non viene arrestata. L'istanza della classe Cache è quindi patrimonio dell'intero dominio dell'applicazione e non si deve commettere l'errore di pensare che sia associata ad una singola pagina o ad una sessione specifica.
E' possibile accedere ai metodi ed alle proprietà dell'istanza Cache attraverso le proprietà pubbliche "Cache" esposte sia dall'oggetto HttpContext sia dall'oggetto Page. Il suo sistema di funzionamento è molto simile ad un dizionario.
Ci sono tre modi per inserire elementi nella Cache:
  1. specificando una chiave e il valore dell'elemento;
  2. utilizzando la funzione Add;
  3. utilizzando la funzione Insert.
Il primo dei tre metodi è sicuramente il più semplice. All'interno di una pagina ASPX, si potrebbe scrivere:

Cache("nome_chiave") = [valore]

In questo caso stiamo utilizzando implicitamente la proprietà Cache di Page.

Se invece volessimo inserire dei valori nella Cache al di fuori di una pagina ASPX (ad esempio in una libreria), potremmo ricorrere ad HttpContext nel modo seguente:

HttpContext.Current.Cache("nome_chiave") = [valore]

ricordandoci in questo caso di importare lo spazio dei nomi System.Web.

Gli altri due metodi si servono delle funzioni Add ed Insert. Questi due metodi sono simili tra loro, ma il metodo Insert risulta essere sicuramente più flessibile; la funzione Add, infatti, dispone soltanto della seguente versione:

Cache.Add( _
  key As String, _
  value As Object, _
  dependencies As CacheDependecy, _
  absoluteExpiration As Date, _
  slidingExpiration As TimeSpan, _
  priority As CacheItemPriority, _
  onRemoveCallBack As CacheItemRemovedCallback_
)

mentre la funzione Insert dispone di ben 4 diverse firme:

Cache.Insert(key As String, value As Object)

Cache.Insert(key As String, value As Object, dependencies As CacheDependecy)

Cache.Insert( _   key As String, _   value As Object, _   dependencies As CacheDependecy, _   absoluteExpiration As Date, _   slidingExpiration As TimeSpan _ )

Cache.Insert( _   key As String, _   value As Object, _   dependencies As CacheDependecy, _   absoluteExpiration As Date, _   slidingExpiration As TimeSpan, _   priority As CacheItemPriority, _   onRemoveCallBack As CacheItemRemovedCallback _ )

Esaminiamo brevemente i parametri richiesti dalle due funzioni:
  • key: rappresenta la chiave dell'oggetto che vogliamo memorizzare in Cache;
  • value: è il dato o l'oggetto che vogliamo memorizzare;
  • dependencies: rappresenta un oggetto dal quale dipende il dato o l'oggetto memorizzato (verrà analizzato meglio in seguito);
  • absoluteExpiration: è la data di scadenza assoluta dell'oggetto in Cache;
  • slidingExpiration: è simile a absoluteExpiration, ma aggiorna la data ogni volta che la pagina viene richiesta;
  • priority: stabilisce come verranno eliminati gli elementi inseriti in Cache in determinate situazioni;
  • onRemoveCallBack: è il metodo che verrà richiamato quando gli elementi vengono rimossi dalla cache.
Per rimuovere invece un elemento in Cache si può utilizzare la funzione Remove, specificando la chiave dell'elemento stesso.

Dim obj As Object = Cache.Remove("nome_chiave")

La funzione Remove restituisce un oggetto del tipo memorizzato e cancella l'oggetto dalla Cache. Questo permette di recuperare (nel caso fosse necessario) per l'ultima volta le informazioni memorizzate nella Cache.

Di seguito riporto un esempio (ampiamente commentato) di utilizzo della Cache in una pagina ASPX tramite le funzioni Add e Remove:

A) Listato esempio1.aspx

<%@ Page Language="VB" %>
<%@ import Namespace="System.Data" %>
<script runat="server">
  Sub Page_Load(sender As Object, e As EventArgs)
    lblMessage.Text = ""
    'Carico i dati
    Dim bIsCached As Boolean = Me.CaricaDati()
    'Visualizzo un messaggio a seconda che i dati siano stati caricati dalla cache o meno
    If Not bIsCached Then
      lblMessage.Text = "Dati Caricati dalla base dati<br />"
    Else
      lblMessage.Text = "Dati Caricati dalla cache<br />"
    End If
  End Sub

  Sub btnExpire_Click(sender As Object, e As EventArgs)
    'Rimuovo esplicitamente i dati dalla cache
    'Da notare che la funzione restituisce per l'ultima volta
    'l'oggetto DataView precedentemente memorizzato

    Dim source As DataView = Me.Cache.Remove("dvUtenti")
    'Ricarico i dati
    Me.CaricaDati()
    lblMessage.Text = "Dati Caricati dalla base dati<br />"
  End Sub

  'Questa funzione si occupa di caricare i dati nel DataGrid.
  'Restituisce un booleano che indica se i dati sono stati caricati
  'dalla base dati o dalla cache.

  Private Function CaricaDati() As Boolean
    Dim bIsCached As Boolean
    'Provo a caricare i dati dalla cache
    Dim source As DataView = Me.Cache("dvUtenti")
    'Controllo se la cache contiene dati
    If isNothing(source) Then
      'Carico i dati dalla fonte
      source = New DataView(Me.CreaData())
      'Aggiungo i dati (secondo parametro) alla cache con chiave "dvUtenti" (primo parametro).
      'L'oggetto non ha nessuna dipendenza (terzo parametro impostato a Nothing).
      'La data di scadenza assoluta è impostata a 10 secondi da ora (quarto parametro).
      'La slidingExpiration è impostata a zero (quinto parametro).
      'onRemoveCallBack impostata a Nothing in quanto non voglio gestire questo evento.

      Me.Cache.Add( _
        "dvUtenti", _
        source, _
        Nothing, _
        DateTime.Now.AddSeconds(10), _
        TimeSpan.Zero, _
        CacheItemPriority.Normal, _
        Nothing _
      )
      bIsCached = False
    Else
      bIsCached = True
    End If
    'Eseguo il Binding del DataGrid
    dgData.DataSource = source
    dgData.DataBind()
    Return bIsCached
  End Function

  'Questa funzione carica dei dati di esempio e li restituisce come tabella.
  Private Function CreaData() As DataTable
    'Creo una nuova Tabella con relative colonne
    Dim oTabella As New DataTable("tbUtenti")
    With oTabella
      .Columns.Add("Nome", System.Type.GetType("System.String"))
      .Columns.Add("Cognome", System.Type.GetType("System.String"))
      .Columns.Add("UserID", System.Type.GetType("System.Int32"))
      .Columns("UserID").AutoIncrement = True
    End With
    'Definisco la chiave primaria della tabella
    Dim chiavi() As DataColumn = {oTabella.Columns("UserID")}
    oTabella.PrimaryKey = chiavi
    'Aggiungo delle righe
    Dim oRows As DataRow
    oRows = oTabella.NewRow()
    oRows(0) = "Leonardo"
    oRows(1) = "Cavone"
    oTabella.Rows.Add(oRows)
    oRows = oTabella.NewRow()
    oRows(0) = "Paolo"
    oRows(1) = "Capitani"
    oTabella.Rows.Add(oRows)
    Return oTabella
  End Function
</script>

<html>
<head>
</head>
<body>
  <form runat="server">
    <asp:Label id="lblMessage" runat="server"></asp:Label>
    <br />
    <br />
    <asp:DataGrid id="dgData" runat="server" BorderColor="#999999" BorderStyle="None" BorderWidth="1px" BackColor="White" CellPadding="3" GridLines="Vertical">
      <FooterStyle forecolor="Black" backcolor="#CCCCCC"></FooterStyle>
      <SelectedItemStyle font-bold="True" forecolor="White" backcolor="#008A8C"></SelectedItemStyle>
      <AlternatingItemStyle backcolor="#DCDCDC"></AlternatingItemStyle>
      <ItemStyle forecolor="Black" backcolor="#EEEEEE"></ItemStyle>
      <HeaderStyle font-bold="True" forecolor="White" backcolor="#000084"></HeaderStyle>
      <PagerStyle horizontalalign="Center" forecolor="Black" backcolor="#999999" mode="NumericPages"></PagerStyle>
    </asp:DataGrid>
    <br />
    <br />
    <asp:Button id="btnInvia" runat="server" Text="Invia" Width="100px"></asp:Button>
    <asp:Button id="btnExpire" onclick="btnExpire_Click" runat="server" Text="Rimuovi Cache" Width="100px"></asp:Button>
  </form>
</body>
</html>

Come accennato precedentemente, le funzioni Add ed Insert permettono di specificare, tramite il parametro "dependency", una dipendenza dell'oggetto memorizzato in Cache da un altro elemento. Le dipendenze della Cache possono essere create su un file o su altri elementi presenti nella stessa Cache.

Il listato che segue è una versione leggermente modificata di quello precedente e mostra come recuperare e memorizzare i dati contenuti in un file XML nella Cache e come aggiungere una dipendenza al file stesso. La prima volta che la pagina ASPX viene richiesta, i dati verranno caricati dal file XML; le successive richieste recupereranno i dati dalla cache. Una modifica dei dati del file XML (con un editor qualsiasi) determineranno l'invalidazione della cache e il ricaricamento dei dati dal file XML.
Per un corretto funzionamento della pagina è necessario salvare il file XML nella stessa directory del file ASPX.

A) Listato utenti.xml

<?xml version="1.0" encoding="utf-8" ?>
<utenti>
  <tbUtenti>
    <Nome>Leonardo</Nome>
    <Cognome>Cavone</Cognome>
    <UserID>1</UserID>
  </tbUtenti>
  <tbUtenti>
    <Nome>Paolo</Nome>
    <Cognome>Capitani</Cognome>
    <UserID>2</UserID>
  </tbUtenti>  
</utenti>

B) Listato esempio2.aspx

<%@ Page Language="VB" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.IO" %>
<script runat="server">
  Sub Page_Load(sender As Object, e As EventArgs)
    lblMessage.Text = ""
    'Carico i dati
    Dim bIsCached As Boolean = Me.CaricaDati()
    'Visualizzo un messaggio a seconda che i dati siano stati caricati dalla cache o meno
    If Not bIsCached Then
      lblMessage.Text = "Dati Caricati dalla base dati<br />"
    Else
      lblMessage.Text = "Dati Caricati dalla cache<br />"
    End If
  End Sub

  Sub btnExpire_Click(sender As Object, e As EventArgs)
    'Rimuovo esplicitamente i dati dalla cache
    'Da notare che la funzione restituisce per l'ultima volta
    'l'oggetto DataView precedentemente memorizzato

    Dim source As DataView = Me.Cache.Remove("dvUtenti")
    'Ricarico i dati
    Me.CaricaDati()
    lblMessage.Text = "Dati Caricati dalla base dati<br />"
  End Sub

  'Questa funzione si occupa di caricare i dati nel DataGrid.
  'Restituisce un booleano che indica se i dati sono stati caricati
  'dalla base dati o dalla cache.

  Private Function CaricaDati() As Boolean
    Dim bIsCached As Boolean
    'Provo a caricare i dati dalla cache
    Dim source As DataView = Me.Cache("dvUtenti")
    'Controllo se la cache contiene dati
    If isNothing(source) Then
      'Memorizzo in una variabile il path del file XML
      Dim sPathFile As String = Server.MapPath("utenti.xml")
      'Carico i dati dalla fonte
      source = New DataView(Me.CreaData(sPathFile))

      'Creo l'oggetto di dipendenza della cache
      Dim oDepend As New CacheDependency(sPathFile)
      'Aggiungo i dati (secondo parametro) alla cache con chiave "dvUtenti" (primo parametro).
      'L'oggetto ha dipendenza dal file XML "utenti.xml" (terzo parametro).
      'La data di scadenza assoluta è impostata a 1 minuto da ora (quarto parametro).
      'La slidingExpiration è impostata a zero (quinto parametro).
      'onRemoveCallBack impostata a Nothing in quanto non voglio gestire questo evento.

      Me.Cache.Insert( _
        "dvUtenti", _
        source, _
        oDepend, _
        DateTime.Now.AddMinutes(1), _
        TimeSpan.Zero _
      )
      bIsCached = False
    Else
      bIsCached = True
    End If
    'Eseguo il Binding del DataGrid
    dgData.DataSource = source
    dgData.DataBind()
    Return bIsCached
  End Function

  'Questa funzione carica dei dati di esempio da un file XML
  'e li restituisce come tabella.

  Private Function CreaData(ByVal sPathFile As String ) As DataTable
    Dim oDependence As New CacheDependency(sPathFile)
    Dim oFileStream As FileStream = New FileStream(sPathFile, FileMode.Open, FileAccess.Read)
    Dim oReader As StreamReader = New StreamReader(oFileStream)
    Dim oDS As New DataSet()
    oDS.ReadXml(oReader)
    oFileStream.Close()
    Dim oTabella As DataTable = oDS.Tables(0)
    oDS.Dispose
    Return oTabella
  End Function
</script>

<html>
<head>
</head>
<body>
  <form runat="server">
    <asp:Label id="lblMessage" runat="server"></asp:Label>
    <br />
    <br />
    <asp:DataGrid id="dgData" runat="server" GridLines="Vertical" CellPadding="3" BackColor="White" BorderWidth="1px" BorderStyle="None" BorderColor="#999999">
      <FooterStyle forecolor="Black" backcolor="#CCCCCC"></FooterStyle>
      <SelectedItemStyle font-bold="True" forecolor="White" backcolor="#008A8C"></SelectedItemStyle>
      <AlternatingItemStyle backcolor="#DCDCDC"></AlternatingItemStyle>
      <ItemStyle forecolor="Black" backcolor="#EEEEEE"></ItemStyle>
      <HeaderStyle font-bold="True" forecolor="White" backcolor="#000084"></HeaderStyle>
      <PagerStyle horizontalalign="Center" forecolor="Black" backcolor="#999999" mode="NumericPages"></PagerStyle>
    </asp:DataGrid>
    <br />
    <br />
    <asp:Button id="btnInvia" runat="server" Width="100px" Text="Invia"></asp:Button>
    <asp:Button id="btnExpire" onclick="btnExpire_Click" runat="server" Width="100px" Text="Rimuovi Cache"></asp:Button>
  </form>
</body>
</html>

E' chiaro che il sistema di Caching dei dati offerto da ASP.NET permette di incrementare enormemente il rendimento di un'applicazione Web. E' bene però ricordare che, ad eccezione del sistema di Caching dell'Output, i dati e gli oggetti inseriti nell'oggetto Cache risiedono nella memoria del server. Questo potrebbe comportare una diminuzione del rendimento del server Web a seconda delle dimensioni degli oggetti memorizzati e dell'equipaggiamento del server stesso. Fortunatamente ASP.NET fornisce anche un meccanismo per espellere automaticamente gli elementi quando la memoria scarseggia. Rimane comunque buona pratica non abusarne.

Download

Cliccando sul link seguente è possibile scaricare i due file aspx dei listati presenti in questo articolo e il file XML del secondo esempio.




Utenti connessi: 7999