Galileo Computing < openbook >
Galileo Computing - Programming the Net
Galileo Computing - Programming the Net


Einstieg in ASP.NET von Matthias Lohrer
Einstieg in ASP.NET
gp Kapitel 15 Leistungssteigerung durch Caching
  gp 15.1 Ganze Seiten cachen
    gp 15.1.1 Formulare cachen
  gp 15.2 Teile von Seiten cachen
    gp 15.2.1 Benutzersteuerelemente cachen, die Formulare enthalten
  gp 15.3 Cache-Einstellungen mit der Klasse HttpCachePolicy programmgesteuert beeinflussen
  gp 15.4 Beliebige Daten und Objekte im Cache ablegen
  gp 15.5 Den Cache automatisch aktualisieren
    gp 15.5.1 Den Cache vom Inhalt einer XML-Datei abhängig machen
    gp 15.5.2 Weitere Möglichkeiten, den Cache abhängig zu machen
    gp 15.5.3 Den Cache über Prioritäten steuern
    gp 15.5.4 Reagieren, wenn ein Eintrag aus dem Cache gelöscht wird
  gp 15.6 Allgemeine Tipps zur Steigerung der Performance
  gp 15.7 Weiterführende Ressourcen


Galileo Computing

15.5 Den Cache automatisch aktualisieren  downtop


Galileo Computing

15.5.1 Den Cache vom Inhalt einer XML-Datei abhängig machen  downtop

Bei der Arbeit mit einem Cache muss man immer wieder raten und schätzen, wie lange eine Information sinnvollerweise im Cache gehalten werden sollte, bevor man sie vielleicht doch lieber neu erstellt. Wenn Sie beispielsweise auf der Website News darstellen und diese Seite stets für fünf Minuten im Cache bleibt, dann wird eine neue Meldung manchmal erst fünf Minuten nach der Aktualisierung auf den Browsern der Anwender erscheinen. Wenn Sie aber stets so aktuell wie möglich sein möchten, gibt es die Möglichkeit, den Cache punktgenau immer dann zu aktualisieren, wenn sich die zugrunde liegenden Daten ändern.

cache_09.aspx und cache_09.xml demonstrieren, wie der Inhalt des Caches an den Inhalt einer XML-Datei gekoppelt wird. Sobald die Datei geändert wird, wird automatisch auch der Cache aktualisiert. Abbildung 15.7 zeigt die Darstellung im Browser.

<!-- cache_09.aspx --> 
<%@ Page Language="VB" Debug="True" Strict="True" 
         EnableViewState="false" %>
<%@ Import namespace="System.Data" %>
<%@ Import namespace="System.Xml" %>
<script runat="server">
Dim t As String
Sub Page_Load (ByVal Sender As Object, _
               ByVal E As EventArgs)
   Dim cacheKey As String = "News"
   Dim myDS As DataSet
   myDS = CType(Cache(cacheKey), DataSet)
   If myDS Is Nothing Then
      Dim xmlDatNam As String = "cache_09.xml"
      ' Daten aus der XML-Datei einlesen
      myDs = New DataSet()
      Dim xdoc As New XmlDataDocument()
      xdoc.DataSet.ReadXml(Server.MapPath(xmlDatNam))
      myDS = xdoc.DataSet
      ' Daten im Cache ablegen
      Dim dep As New CacheDependency _
                           (Server.MapPath(xmlDatNam))
      Cache.Insert (cacheKey, myDS, dep)
      ausgabe.innerText = "Quelle: Neu geladen"
   Else
      ausgabe.innerText = "Quelle: Cache" 
   End If
   dg.DataSource = myDS.Tables(2)
   dg.DataBind()              
End Sub
</script>
<html>
<head><title>Ein Cache-Objekt vom Inhalt einer 
XML-Datei abhängig machen</title></head>
<body>
<h3>Ein Cache-Objekt vom Inhalt einer 
XML-Datei abhängig machen</h3>
<form runat="server" >
<h3>Aktuelle News</h3>
<asp:DataGrid runat="server"
              id="dg" >
</asp:DataGrid>
<p id="ausgabe" runat="server" />
</form></body></html>

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 15.7 Bei jeder Änderung in der XML-Datei wird der Cache automatisch aktualisiert.

<xml version="1.0" encoding='utf-8' >
<news>
<message>
<Datum>15.12.2002</Datum>
<Titel>Preis für Monitor "Gucki" halbiert.</Titel>
</message>
<message>
<Datum>14.12.2002</Datum>
<Titel>Teetasse "Hubert" jetzt viel billiger</Titel>
</message>
<message>
<Datum>13.12.2002</Datum>
<Titel>Das Sofa "Urmel" jetzt auch in Rot erhältlich.</Titel>
</message>
</news>
</xml>

Die Seite cache_09.aspx stellt die News in einer Tabelle dar. Diese Tabelle wird über ein serverseitiges DataGrid-Steuerelement erzeugt. Beim Laden der Seite cache_09.aspx wird ein DataSet-Objekt an dieses Steuerelement gebunden. Dieses DataSet-Objekt wird im Cache gehalten. In Page_Load ist außerdem der Fall vorgesehen, dass es noch kein entsprechendes Cache-Objekt gibt. In diesem Fall werden die Daten aus der XML-Datei eingelesen und neu im Cache abgelegt.

Beim Ablegen des DataSet-Objekts im Cache wird eine Cache-Abhängigkeit definiert.

Dim dep As New CacheDependency _
                           (Server.MapPath(xmlDatNam))

Server.MapPath erstellt den physischen Dateipfad zu dem übergebenen (virtuellen) Dateinamen. Diesen physischen Dateipfad benötigen Sie für den Konstruktor der CacheDependency-Klasse. Das bedeutet: Ein Cache-Element soll von dieser Datei abhängig sein. Sobald diese Datei sich ändert, soll das entsprechende Cache-Element aus dem Cache entfernt werden. Mit der nächsten Zeile wird das DataSet-Objekt mit dem in cacheKey enthaltenen Schlüssel und der in dep definierten Cache-Abhängigkeit in den Cache eingefügt.

Cache.Insert (cacheKey, myDS, dep)

Sobald die XML-Datei sich ändert, wird sie aus dem Cache entfernt. Der Cache wird aber nicht automatisch aktualisiert. Das müssen Sie selbst erledigen, und genau das macht die Page_Load-Prozedur.

Die Bindung an das DataGrid-Steuerelement erfolgt mit dieser Zeile:

dg.DataSource = myDS.Tables(2)

Das DataSet-Objekt enthält mehrere Tabellen. Die beiden ersten Tabellen enthalten strukturelle Informationen über den XML-Datenbestand. Erst die dritte Tabelle mit der Ordnungszahl 2 enthält die eigentlichen Datensätze. Eine Spalte news_Id wurde automatisch ergänzt und soll hier nicht weiter stören.


Galileo Computing

15.5.2 Weitere Möglichkeiten, den Cache abhängig zu machen  downtop

cache_09.aspx hat demonstriert, wie ein Cache-Objekt vom Inhalt einer XML-Datei abhängig gemacht werden kann. Es gibt weitere Möglichkeiten, den Cache vom Status anderer Elemente abhängig zu machen.


Tipp   Diese Möglichkeiten erschließen sich alle über die diversen Konstruktoren der CacheDependency-Klasse. Hier einige Beispiele:

Public Sub New(String())

Sie können den Cache von mehreren Dateien oder Verzeichnissen abhängig machen, indem Sie die entsprechenden Pfade in einem Array übergeben.

Public Sub New(String, DateTime)

Mit diesem Konstruktor übergeben Sie zusätzlich zu einem Dateipfad eine Zeitangabe. Die Überwachung startet zum genannten Zeitpunkt.

Der folgende Konstruktor bietet die Möglichkeit, einen Cache von mehreren Dateipfaden und von mehreren anderen Cache-Elementen abhängig zu machen. Im ersten Array werden die Dateiabhängigkeiten übergeben, das zweite Array führt die abhängigen Cache-Elemente auf:

Public Sub New(String(), String())

Galileo Computing

15.5.3 Den Cache über Prioritäten steuern  downtop

Wenn Sie mit der Add- oder Insert-Methode ein Objekt im Cache ablegen, können Sie zusätzlich einen Wert für die Priorität angeben. Wenn es im Arbeitsspeicher des Webservers eng wird, dann werden zunächst die Objekte mit niedrigerer Cache-Priorität aus dem Arbeitsspeicher entfernt. Tabelle 15.3 nennt die gültigen Abstufungen, die in der Enumeration CacheItemPriority enthalten sind.


Wert Bedeutung
NotRemovable Das Objekt wird gar nicht gelöscht.
High Das Objekt wird nur in Extremfällen gelöscht.
AboveNormal Höher als Normal, geringer als High
Default Default und Normal bedeuten die gleiche Stufe.
Normal Default und Normal bedeuten die gleiche Stufe.
BelowNormal Höher als Low, niedriger als Normal
Low Objekte mit dem Wert Low werden als Erste aus dem Speicher gelöscht.

Tabelle 15.3 Die Werte der Enumeration CacheItemPriority in absteigender Priorität geordnet

Der folgende Befehl fügt das Objekt myDS mit der Priorität High in den Cache ein.

Cache.Insert (cacheKey, _
              myDS, _
              dep, _
              DateTime.MaxValue, _
              TimeSpan.Zero, _
              CacheItemPriority.High, _
              Nothing)

Der letzte Parameter bezeichnet einen Wert für den Callback Support. Das ist das Thema des nächsten Abschnitts.


Galileo Computing

15.5.4 Reagieren, wenn ein Eintrag aus dem Cache gelöscht wird  toptop

ASP.NET bietet die Möglichkeit zu reagieren, wenn ein Eintrag aus dem Cache gelöscht wird. Dafür stellt ASP.NET den CacheItemRemovedCallback-Delegaten zur Verfügung. Eine entsprechende Funktionalität implementieren Sie in vier Schritten:

gp  Sie definieren eine lokale Variable vom Typ CacheItemRemovedCallback.
gp  Sie definieren eine entsprechende Ereignisprozedur.
gp  Sie weisen der lokalen Variablen die Adresse der Ereignisprozedur zu.
gp  Wenn Sie das Objekt in den Cache einfügen, geben Sie zusätzlich diese Variable an.

Zur Demonstration dieses Verfahrens kann cache_07.aspx ganz gut abgewandelt werden. cache_10.aspx zeigt, wie bei jeder Entfernung aus dem Cache eine Logdatei aktualisiert wird. Hier folgt zunächst der komplette Quellcode, an den sich die Erläuterungen anschließen. Abbildung 15.8 zeigt parallel zum Browser den Editor mit der automatisch erstellten Logdatei.

<!-- cache_10.aspx --> 
<%@ Page Language="VB" Debug="True" Strict="True" %>
<script runat="server">
Private Shared onRemove _ 
                As CacheItemRemovedCallback = Nothing
Sub btnOK_Click _
              (Sender As Object, E As System.EventArgs)
   onRemove = new CacheItemRemovedCallback _
                   (AddressOf Me.RemovedFromCache)
   Cache.Insert("Topmeldung", _
                TopText.value, _
                Nothing, _
                DateTime.Now.AddSeconds(10), _
                TimeSpan.Zero, _
                CacheItemPriority.Default, _
                onRemove )
   ausgabe.innerText = TopText.value
End Sub

Sub btnDelete_Click _
              (Sender As Object, E As System.EventArgs)
   Cache.Remove("Topmeldung")
   ausgabe.innerText = ""
   TopText.value=""
End Sub

Public Sub RemovedFromCache _
                   (key As String, _
                    value As Object, _
                    reason As CacheItemRemovedReason )
   Dim w As System.IO.StreamWriter
   w = new System.IO.StreamWriter _
                     ("c:\\cachelog.txt", true)
   w.WriteLine(DateTime.Now.ToString() _
        & " " _
        & key _
        & ": " _
        & value.ToString() _
        & " – " _
        & reason.ToString())
   w.Close()
End Sub          
</script>
<html><head><title>
Auf das Ereignis reagieren, dass ein Eintrag aus dem 
Cache entfernt wird</title></head>
<body>
<h3>Auf das Ereignis reagieren, dass ein Eintrag aus 
dem Cache entfernt wird</h3>
<form runat="server" >
Topmeldung<br>
<p>Aktuell gespeichert: 
<span id="ausgabe" runat="server" /></p>
<input type="text" id="TopText" runat="server" 
       size="60">
<br>
<asp:Button runat="server" id="btnOK"
            OnClick="btnOK_Click" 
            Text="Meldung speichern" />
<br><br>
<asp:Button runat="server" id="btnDelete"
            OnClick="btnDelete_Click"
            Text="Meldung löschen" />            
</form>
<p>
<a href="c:\cachelog.txt">Cache-Log ansehen</a>
</p></body></html>

Abbildung
Hier klicken, um das Bild zu Vergrößern

Abbildung 15.8 Mit einem Delegaten reagieren Sie auf das Entfernen eines Eintrags aus dem Cache.

Die Ereignisprozedur definieren

Zunächst benötigen Sie eine Prozedur, die beim Eintreten des Ereignisses Eintrag wird aus dem Cache gelöscht ausgeführt werden soll. Dieser Ereignisprozedur werden drei Werte übergeben:

gp  der Schlüssel des Cache-Eintrags,
gp  das gecachte Objekt selbst und
gp  eine Angabe zum Grund, warum der Eintrag aus dem Cache entfernt wird.

Damit ergibt sich diese Signatur:

Public Sub RemovedFromCache _
                   (key As String, _
                    value As Object, _
                    reason As CacheItemRemovedReason )

CacheItemRemovedReason ist eine Enumeration, die vier verschiedene Gründe für die Entfernung aus dem Cache angeben kann. Tabelle 15.4 nennt die möglichen Werte.


Wert Bedeutung
DependencyChanged Das Element wird entfernt, da eine der definierten Abhängigkeiten sich geändert hat. Beispiel: Die verknüpfte Datei hat sich geändert.
Expired Die Gültigkeit ist abgelaufen.
Removed Die Removed-Methode wurde aufgerufen oder es wurde ein neuer Eintrag mit dem gleichen Schlüssel definiert.
Underused Der Eintrag wurde gelöscht, weil das System Arbeitsspeicher benötigt hat.

Tabelle 15.4 Die Werte der Enumeration CacheItemRemovedReason

cache_10.aspx definiert innerhalb dieser Prozedur die nötigen Schritte, um eine Logdatei zu führen. Wann immer ein Eintrag aus dem Cache gelöscht wird, fügt die Prozedur in der Logdatei eine Zeile an. Dabei hält sie den Zeitpunkt, den Wert des Schlüssels, den Inhalt des Objekts und den Grund für das Löschen fest.

Public Sub RemovedFromCache _
                   (key As String, _
                    value As Object, _
                    reason As CacheItemRemovedReason )
   Dim w As System.IO.StreamWriter
   w = new System.IO.StreamWriter _
                     ("c:\\cachelog.txt", true)
   w.WriteLine(DateTime.Now.ToString() _
        & " " _
        & key _
        & ": " _
        & value.ToString() _
        & " – " _
        & reason.ToString())
   w.Close()
End Sub

Die Ereignisprozedur mit dem Ereignis verknüpfen

Im umgebenden script-Block von cache_10.aspx wird zunächst die lokale, statische Variable onRemove als CacheItemRemovedCallback-Objekt deklariert. In der Prozedur btnOK_Click wird jeweils der Cache aktualisiert. Hier erhält die Variable onRemove mit Hilfe des AddressOf-Operators die Adresse der Prozedur RemovedFromCache als Wert. Damit können Sie beim Aufruf der Methode Cache.Insert die Variable onRemove als Parameter übergeben und haben so das Ereignis erfolgreich mit der Ereignisprozedur verknüpft.

  

Einstieg in VB.NET

VB.NET

Einstieg in C#

Visual C#

VB.NET und Datenbanken

Einstieg in XML




Copyright © Galileo Press GmbH 2003
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Gartenstraße 24, 53229 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de