Freigeben über


Zwischenspeichern von Daten in der Architektur (C#)

von Scott Mitchell

PDF herunterladen

Im vorherigen Lernprogramm haben wir gelernt, wie Sie die Zwischenspeicherung auf der Präsentationsebene anwenden. In diesem Lernprogramm erfahren Sie, wie Sie unsere mehrschichtige Architektur nutzen, um Daten auf der Geschäftslogikebene zwischenzuspeichern. Dazu erweitern wir die Architektur um eine Caching-Ebene.

Einleitung

Wie wir im vorherigen Lernprogramm gesehen haben, ist das Zwischenspeichern der ObjectDataSource-Daten so einfach wie das Festlegen einiger Eigenschaften. Leider wendet ObjectDataSource Zwischenspeicherung auf der Präsentationsebene an, wodurch die Zwischenspeicherungsrichtlinien eng mit der ASP.NET Seite gekoppelt werden. Einer der Gründe für die Erstellung einer mehrschichtigen Architektur besteht darin, solche Kopplungen zu zerbrechen. Die Geschäftslogikebene entkoppelt beispielsweise die Geschäftslogik von den ASP.NET Seiten, während die Datenzugriffsschicht die Datenzugriffsdetails entkoppelt. Diese Entkoppelung von Geschäftslogik- und Datenzugriffsdetails wird teilweise bevorzugt, da das System besser lesbar, besser verwaltet und flexibler geändert werden kann. Es fördert auch das Domänenwissen und die Arbeitsteilung; ein Entwickler, der an der Präsentationsschicht arbeitet, muss die Details der Datenbank nicht kennen, um seine Arbeit zu erledigen. Das Decoupieren der Zwischenspeicherungsrichtlinie von der Präsentationsebene bietet ähnliche Vorteile.

In diesem Lernprogramm erweitern wir unsere Architektur, um eine Caching-Ebene (oder cl kurz gesagt) einzuschließen, die unsere Caching-Richtlinie verwendet. Die Caching-Ebene enthält eine ProductsCL Klasse, die Zugriff auf Produktinformationen mit Methoden wie GetProducts(), GetProductsByCategoryID(categoryID)usw. bietet, die beim Aufrufen zuerst versuchen, die Daten aus dem Cache abzurufen. Wenn der Cache leer ist, rufen diese Methoden die entsprechende ProductsBLL Methode in der BLL auf, wodurch wiederum die Daten aus dem DAL abgerufen werden. Die ProductsCL Methoden speichern die aus der BLL abgerufenen Daten zwischen, bevor sie zurückgegeben werden.

Wie in Abbildung 1 dargestellt, befindet sich die CL zwischen den Ebenen "Präsentation" und "Geschäftslogik".

Die Caching-Ebene (CL) ist eine weitere Ebene in unserer Architektur

Abbildung 1: Die Cacheschicht (CL) ist eine weitere Ebene in unserer Architektur.

Schritt 1: Erstellen der Zwischenspeicherungsebenenklassen

In diesem Lernprogramm erstellen wir eine sehr einfache CL mit einer einzigen Klasse ProductsCL , die nur eine Handvoll Methoden enthält. Das Erstellen einer vollständigen Caching-Schicht für die gesamte Anwendung erfordert die Erstellung der Klassen CategoriesCL, EmployeesCL und SuppliersCL sowie das Anbieten einer Methode in diesen Caching-Schicht-Klassen für jede Datenzugriffs- oder Änderungsmethode in der BLL. Wie bei der BLL und DAL sollte die Caching-Ebene idealerweise als separates Klassenbibliotheksprojekt implementiert werden; Wir implementieren sie jedoch als Klasse im App_Code Ordner.

Um die CL-Klassen sauberer von den DAL- und BLL-Klassen zu trennen, erstellen wir einen neuen Unterordner im App_Code Ordner. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den App_Code Ordner, wählen Sie "Neuer Ordner" aus, und nennen Sie den neuen Ordner CL. Fügen Sie nach dem Erstellen dieses Ordners eine neue Klasse mit dem Namen ProductsCL.cshinzu.

Hinzufügen eines neuen Ordners mit dem Namen CL und einer Klasse mit dem Namen ProductsCL.cs

Abbildung 2: Hinzufügen eines neuen Ordners namens CL und einer Benannten Klasse ProductsCL.cs

Die ProductsCL Klasse sollte den gleichen Satz von Datenzugriffs- und Änderungsmethoden enthalten wie in der entsprechenden Business Logic Layer-Klasse (ProductsBLL). Anstatt alle diese Methoden zu erstellen, erstellen wir hier nur ein paar, um ein Gefühl für die von der CL verwendeten Muster zu erhalten. Insbesondere werden wir die Methoden GetProducts() und GetProductsByCategoryID(categoryID) in Schritt 3 sowie eine UpdateProduct-Überladung in Schritt 4 hinzufügen. Sie können die übrigen ProductsCL Methoden und CategoriesCL, EmployeesCL und SuppliersCL Klassen in Ihrer Freizeit hinzufügen.

Schritt 2: Lesen und Schreiben in den Datencache

Das im vorherigen Lernprogramm untersuchte Feature zum Zwischenspeichern von ObjectDataSource verwendet intern den ASP.NET Datencache, um die aus der BLL abgerufenen Daten zu speichern. Auf den Datencache kann auch programmatisch über Code-Behind-Klassen von ASP.NET-Seiten oder über Klassen in der Architektur der Webanwendung zugegriffen werden. Verwenden Sie das folgende Muster, um den Datencache aus einer Code-behind-Klasse einer ASP.NET-Seite zu lesen und in den Datencache zu schreiben.

// Read from the cache
object value = Cache["key"];
// Add a new item to the cache
Cache["key"] = value;
Cache.Insert(key, value);
Cache.Insert(key, value, CacheDependency);
Cache.Insert(key, value, CacheDependency, DateTime, TimeSpan);

Die Cache Methode der Insert Klasse weist eine Reihe von Überladungen auf. Cache["key"] = value und Cache.Insert(key, value) sind synonym und fügen beide mithilfe des angegebenen Schlüssels ein Element ohne definierten Ablauf zum Cache hinzu. In der Regel möchten wir beim Hinzufügen eines Elements zum Cache eine Ablaufzeit angeben, entweder als Abhängigkeit oder zeitbasiert, oder beides. Verwenden Sie eine der anderen Insert Methodenüberladungen, um Abhängigkeits- oder zeitbasierte Ablaufinformationen bereitzustellen.

Die Methoden der Caching Layer müssen zuerst überprüfen, ob sich die angeforderten Daten im Cache befinden und wenn ja, von dort zurückgeben. Wenn sich die angeforderten Daten nicht im Cache befinden, muss die entsprechende BLL-Methode aufgerufen werden. Der Rückgabewert sollte zwischengespeichert und dann zurückgegeben werden, wie das folgende Sequenzdiagramm veranschaulicht.

Die Methoden der Cacheebene geben Daten aus dem Cache zurück, wenn sie verfügbar ist.

Abbildung 3: Die Methoden der Cacheebene geben Daten aus dem Cache zurück, wenn sie verfügbar ist.

Die in Abbildung 3 dargestellte Sequenz wird in den CL-Klassen mithilfe des folgenden Musters erreicht:

Type instance = Cache["key"] as Type;
if (instance == null)
{
    instance = BllMethodToGetInstance();
    Cache.Insert(key, instance, ...);
}
return instance;

Hier ist Type der Typ der Daten, die im Cache Northwind.ProductsDataTablegespeichert werden, z. B. während der Schlüssel der Schlüssel ist, der das Cacheelement eindeutig identifiziert. Wenn sich das Element mit dem angegebenen Schlüssel nicht im Cache befindet, wird die Instanz auf null gesetzt und die Daten werden aus der entsprechenden BLL-Methode abgerufen und dem Cache hinzugefügt. Wenn return instance erreicht ist, enthält die Instanz einen Verweis auf die Daten, entweder aus dem Cache oder aus der BLL bezogen.

Achten Sie darauf, das obige Muster beim Zugriff auf Daten aus dem Cache zu verwenden. Das folgende Muster, das auf den ersten Blick gleich aussieht, enthält einen subtilen Unterschied, der eine Rennbedingung einführt. Rennbedingungen sind schwer zu debuggen, da sie sich sporadisch offenbaren und schwer zu reproduzieren sind.

if (Cache["key"] == null)
{
    Cache.Insert(key, BllMethodToGetInstance(), ...);
}
return Cache["key"];

Der Unterschied in diesem zweiten, falschen Codeausschnitt besteht darin, dass, anstatt einen Verweis auf das zwischengespeicherte Element in einer lokalen Variablen zu speichern, direkt auf den Datencache in der Bedingungsanweisung und in der return zugegriffen wird. Stellen Sie sich vor, dass bei Erreichen dieses Codes Cache["key"] nicht null ist, aber bevor die return-Anweisung erreicht wird, entfernt das System den Schlüssel aus dem Cache. In diesem seltenen Fall gibt der Code anstelle eines Objekts des erwarteten Typs einen null Wert zurück.

Hinweis

Der Datencache ist threadsicher, sodass Sie den Threadzugriff nicht für einfache Lese- oder Schreibvorgänge synchronisieren müssen. Wenn Sie jedoch mehrere Vorgänge für Daten im Cache ausführen müssen, die atomar sein müssen, sind Sie für die Implementierung einer Sperre oder eines anderen Mechanismus verantwortlich, um die Threadsicherheit sicherzustellen. Weitere Informationen finden Sie unter "Zugriff auf den ASP.NET-Cache synchronisieren".

Ein Element kann mithilfe der Remove folgenden Methode programmgesteuert aus dem Datencache entfernt werden:

Cache.Remove(key);

Schritt 3: Zurückgeben von Produktinformationen aus derProductsCLKlasse

In diesem Lernprogramm werden zwei Methoden zum Zurückgeben von Produktinformationen aus der ProductsCL Klasse implementiert: GetProducts() und GetProductsByCategoryID(categoryID). Wie bei der Klasse in der Geschäft ProductsBL Logikschicht gibt die GetProducts()-Methode in der CL Informationen über alle Produkte als Northwind.ProductsDataTable-Objekt zurück, während GetProductsByCategoryID(categoryID) alle Produkte aus einer angegebenen Kategorie zurückgibt.

Der folgende Code zeigt einen Teil der Methoden in der ProductsCL Klasse:

[System.ComponentModel.DataObject]
public class ProductsCL
{
    private ProductsBLL _productsAPI = null;
    protected ProductsBLL API
    {
        get
        {
            if (_productsAPI == null)
                _productsAPI = new ProductsBLL();
            return _productsAPI;
        }
    }
    
   [System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
    public Northwind.ProductsDataTable GetProducts()
    {
        const string rawKey = "Products";
        // See if the item is in the cache
        Northwind.ProductsDataTable products = _
            GetCacheItem(rawKey) as Northwind.ProductsDataTable;
        if (products == null)
        {
            // Item not found in cache - retrieve it and insert it into the cache
            products = API.GetProducts();
            AddCacheItem(rawKey, products);
        }
        return products;
    }
    
    [System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select, false)]
    public Northwind.ProductsDataTable GetProductsByCategoryID(int categoryID)
    {
        if (categoryID < 0)
            return GetProducts();
        else
        {
            string rawKey = string.Concat("ProductsByCategory-", categoryID);
            // See if the item is in the cache
            Northwind.ProductsDataTable products = _
                GetCacheItem(rawKey) as Northwind.ProductsDataTable;
            if (products == null)
            {
                // Item not found in cache - retrieve it and insert it into the cache
                products = API.GetProductsByCategoryID(categoryID);
                AddCacheItem(rawKey, products);
            }
            return products;
        }
    }
}

Notieren Sie sich zunächst die Attribute, die auf die Klasse und die Methoden angewendet werden, DataObject und DataObjectMethodAttribute. Diese Attribute enthalten Informationen für den ObjectDataSource-Assistenten, der angibt, welche Klassen und Methoden in den Schritten des Assistenten angezeigt werden sollen. Da auf die CL-Klassen und -Methoden über eine ObjectDataSource in der Präsentationsebene zugegriffen wird, habe ich diese Attribute hinzugefügt, um die Entwurfszeit zu verbessern. Im Lernprogramm zum Erstellen einer Geschäftslogikebene finden Sie eine ausführlichere Beschreibung zu diesen Attributen und deren Auswirkungen.

In den GetProducts() Und GetProductsByCategoryID(categoryID) Methoden werden die von der GetCacheItem(key) Methode zurückgegebenen Daten einer lokalen Variablen zugewiesen. Die GetCacheItem(key) Methode, die wir kurz untersuchen, gibt ein bestimmtes Element aus dem Cache basierend auf dem angegebenen Schlüssel zurück. Wenn keine solchen Daten im Cache gefunden werden, wird sie aus der entsprechenden ProductsBLL Klassenmethode abgerufen und dann mithilfe der AddCacheItem(key, value) Methode zum Cache hinzugefügt.

Die Methoden GetCacheItem(key) und AddCacheItem(key, value) interagieren mit dem Datencache und lesen bzw. schreiben Werte. Die GetCacheItem(key) Methode ist die einfachere der beiden. Mit dem übergebenen Schlüssel wird einfach der Wert aus der Cache-Klasse zurückgegeben:

private object GetCacheItem(string rawKey)
{
    return HttpRuntime.Cache[GetCacheKey(rawKey)];
}
private readonly string[] MasterCacheKeyArray = {"ProductsCache"};
private string GetCacheKey(string cacheKey)
{
    return string.Concat(MasterCacheKeyArray[0], "-", cacheKey);
}

GetCacheItem(key) verwendet nicht den angegebenen Schlüsselwert, sondern ruft stattdessen die GetCacheKey(key) Methode auf, die den Schlüssel zurückgibt, der mit ProductsCache- vorangestellt ist. Der MasterCacheKeyArray, der die Zeichenfolge ProductsCache enthält, wird auch von der AddCacheItem(key, value)-Methode verwendet, wie wir gleich sehen werden.

Von einer CodeBehind-Klasse einer ASP.NET-Seite aus kann über die Eigenschaft der Klasse Cache auf den Datencache zugegriffen werden, wodurch eine Syntax wie Cache["key"] = value möglich ist, wie in Schritt 2 beschrieben. Über eine Klasse innerhalb der Architektur kann auf den Datencache mithilfe von entweder HttpRuntime.Cache oder HttpContext.Current.Cache zugegriffen werden. Peter Johnsons Blogeintrag HttpRuntime.Cache vs. HttpContext.Current.Cache stellt den leichten Leistungsvorteil bei der Verwendung HttpRuntime anstelle von HttpContext.Current; folglich ProductsCL verwendet HttpRuntime.

Hinweis

Wenn Ihre Architektur mithilfe von Klassenbibliotheksprojekten implementiert wird, müssen Sie der Assembly einen Verweis System.Web hinzufügen, um die HttpRuntime - und HttpContext-Klassen zu verwenden.

Wenn das Element im Cache nicht gefunden wird, rufen die Methoden der ProductsCL Klasse die Daten aus der BLL ab und fügen es mithilfe der AddCacheItem(key, value) Methode dem Cache hinzu. Um dem Cache Einen Wert hinzuzufügen, können wir den folgenden Code verwenden, der einen Ablauf von 60 Sekunden verwendet:

const double CacheDuration = 60.0;
private void AddCacheItem(string rawKey, object value)
{
    HttpRuntime.Cache.Insert(GetCacheKey(rawKey), value, null, 
        DateTime.Now.AddSeconds(CacheDuration), Caching.Cache.NoSlidingExpiration);
}

DateTime.Now.AddSeconds(CacheDuration) Gibt den zeitbasierten Ablauf von 60 Sekunden in der Zukunft an, während System.Web.Caching.Cache.NoSlidingExpiration anzeigt, dass kein gleitender Ablauf vorhanden ist. Obwohl bei dieser Insert Methodenüberladung Parameter sowohl für eine absolute als auch für eine gleitende Ablaufzeit vorhanden sind, können Sie nur einen von beiden angeben. Wenn Sie versuchen, sowohl eine absolute Zeit als auch eine Zeitspanne anzugeben, löst die Insert Methode eine ArgumentException Ausnahme aus.

Hinweis

Diese Implementierung der AddCacheItem(key, value) Methode weist derzeit einige Mängel auf. Wir werden diese Probleme in Schritt 4 angehen und überwinden.

Schritt 4: Ungültigmachen des Caches, wenn die Daten durch die Architektur geändert werden

Zusammen mit Datenabrufmethoden muss die Cacheschicht dieselben Methoden wie die BLL zum Einfügen, Aktualisieren und Löschen von Daten bereitstellen. Die CL-Datenänderungsmethoden ändern die zwischengespeicherten Daten nicht, sondern rufen die entsprechende BLL-Datenänderungsmethode auf und ungültigen Cache. Wie wir im vorherigen Lernprogramm gesehen haben, ist dies das gleiche Verhalten, das die ObjectDataSource anwendet, wenn die Zwischenspeicherungsfeatures aktiviert sind und ihre Insert, Updateoder Delete Methoden aufgerufen werden.

Die folgende UpdateProduct Überladung veranschaulicht, wie die Datenänderungsmethoden in der CL implementiert werden:

[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
    bool result = API.UpdateProduct(productName, unitPrice, productID);
    // TODO: Invalidate the cache
    return result;
}

Die entsprechende Methode zur Datenänderung von Business Logic Layer wird aufgerufen, aber bevor die Antwort zurückgegeben wird, müssen wir den Cache ungültig machen. Leider ist die Ungültigkeit des Caches nicht einfach, da die ProductsCL Klassen GetProducts() und GetProductsByCategoryID(categoryID) Methoden dem Cache elemente mit unterschiedlichen Schlüsseln hinzufügen, und die GetProductsByCategoryID(categoryID) Methode fügt ein anderes Cacheelement für jede eindeutige Kategorie-ID hinzu.

Beim Ungültigen des Caches müssen alle Elemente entfernt werden, die möglicherweise von der ProductsCL Klasse hinzugefügt wurden. Dies kann erreicht werden, indem eine Cacheabhängigkeit mit den einzelnen Elementen verknüpft wird, die dem Cache in der AddCacheItem(key, value) Methode hinzugefügt wurden. Im Allgemeinen kann eine Cacheabhängigkeit ein anderes Element im Cache, eine Datei im Dateisystem oder Daten aus einer Microsoft SQL Server-Datenbank sein. Wenn sich die Abhängigkeit ändert oder aus dem Cache entfernt wird, werden die zugeordneten Cacheelemente automatisch aus dem Cache entfernt. In diesem Lernprogramm möchten wir ein zusätzliches Element im Cache erstellen, das als Cacheabhängigkeit für alle Elemente dient, die über die ProductsCL Klasse hinzugefügt wurden. Auf diese Weise können alle diese Elemente aus dem Cache entfernt werden, indem einfach die Cacheabhängigkeit entfernt wird.

Lassen Sie uns die AddCacheItem(key, value) Methode aktualisieren, damit jedes Element, das dem Cache über diese Methode hinzugefügt wird, einer einzelnen Cacheabhängigkeit zugeordnet ist:

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Make sure MasterCacheKeyArray[0] is in the cache - if not, add it
    if (DataCache[MasterCacheKeyArray[0]] == null)
        DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
    // Add a CacheDependency
    System.Web.Caching.CacheDependency dependency = 
        new CacheDependency(null, MasterCacheKeyArray);
    DataCache.Insert(GetCacheKey(rawKey), value, dependency, 
        DateTime.Now.AddSeconds(CacheDuration), 
        System.Web.Caching.Cache.NoSlidingExpiration);
}

MasterCacheKeyArray ist ein Zeichenfolgenarray, das einen einzelnen Wert enthält, ProductsCache. Zunächst wird dem Cache ein Cacheelement hinzugefügt und dem aktuellen Datum und der aktuellen Uhrzeit zugewiesen. Wenn das Cacheelement bereits vorhanden ist, wird es aktualisiert. Als Nächstes wird eine Cacheabhängigkeit erstellt. Der Konstruktor der CacheDependency Klasse verfügt über mehrere Überladungen, aber die hier verwendete erwartet zwei string Arrayeingaben. Der erste gibt den Satz von Dateien an, die als Abhängigkeiten verwendet werden sollen. Da keine dateibasierten Abhängigkeiten verwendet werden sollen, wird für den ersten Eingabeparameter ein Wert null verwendet. Der zweite Eingabeparameter gibt den Satz von Cacheschlüsseln an, die als Abhängigkeiten verwendet werden sollen. Hier geben wir unsere einzelne Abhängigkeit an. MasterCacheKeyArray Der CacheDependency wird dann an die Insert Methode übergeben.

Bei dieser Änderung von AddCacheItem(key, value) ist das Ungültigmachen des Caches so einfach wie das Entfernen der Abhängigkeit.

[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
    bool result = API.UpdateProduct(productName, unitPrice, productID);
    // Invalidate the cache
    InvalidateCache();
    return result;
}
public void InvalidateCache()
{
    // Remove the cache dependency
    HttpRuntime.Cache.Remove(MasterCacheKeyArray[0]);
}

Schritt 5: Aufrufen der Zwischenspeicherungsebene aus der Präsentationsschicht

Die Klassen und Methoden von Caching Layer können verwendet werden, um mit Daten mithilfe der Techniken zu arbeiten, die wir in diesen Lernprogrammen untersucht haben. Um die Arbeit mit zwischengespeicherten Daten zu veranschaulichen, speichern Sie Die Änderungen an der ProductsCL Klasse, und öffnen Sie dann die FromTheArchitecture.aspx Seite im Caching Ordner, und fügen Sie eine GridView hinzu. Erstellen Sie im Smarttag von GridView eine neue ObjectDataSource. Im ersten Schritt des Assistenten sollte die ProductsCL Klasse als eine der Optionen aus der Dropdown-Liste angezeigt werden.

Die ProductsCL-Klasse ist in der Geschäftsobjektliste Drop-Down enthalten.

Abbildung 4: Die ProductsCL Klasse ist in der Geschäftsobjektliste Drop-Down Liste enthalten (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Klicken Sie nach dem Auswählen ProductsCLauf "Weiter". Die Dropdownliste in der Registerkarte SELECT hat zwei Elemente - GetProducts() und GetProductsByCategoryID(categoryID) - und die Registerkarte "AKTUALISIEREN" hat die einzige UpdateProduct Überladung. Wählen Sie die GetProducts() Methode auf der Registerkarte SELECT und die UpdateProducts Methode auf der Registerkarte "AKTUALISIEREN" aus, und klicken Sie auf "Fertig stellen".

Die ProductsCL-Klassenmethoden werden in den Drop-Down-Listen aufgeführt.

Abbildung 5: Die ProductsCL Methoden der Klasse werden in den Drop-Down-Listen aufgelistet (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Sobald der Assistent abgeschlossen ist, setzt Visual Studio die ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf original_{0} und fügt die entsprechenden Felder zur GridView hinzu. Ändern Sie die OldValuesParameterFormatString Eigenschaft wieder in ihren Standardwert, {0}und konfigurieren Sie die GridView, um Paging, Sortierung und Bearbeitung zu unterstützen. Da die UploadProducts von der CL verwendete Überladung nur den Namen und den Preis des bearbeiteten Produkts akzeptiert, beschränken Sie die GridView so, dass nur diese Felder bearbeitet werden können.

Im vorherigen Tutorial haben wir eine GridView definiert, die die Felder für ProductName, CategoryName und UnitPrice enthält. Sie können diese Formatierung und Struktur replizieren. In diesem Fall sollte ihr deklaratives GridView- und ObjectDataSource-Markup ähnlich wie folgt aussehen:

<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False" 
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
    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") %>'></asp:Label>
            </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="ProductsDataSource" 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>

An diesem Punkt haben wir eine Seite, die die Caching-Ebene verwendet. Um den Cache in Aktion anzuzeigen, legen Sie Haltepunkte in den ProductsCL Klassen GetProducts() und UpdateProduct Methoden fest. Besuchen Sie die Seite in einem Browser, und durchlaufen Sie den Code beim Sortieren und Paging, um die aus dem Cache abgerufenen Daten anzuzeigen. Aktualisieren Sie dann einen Datensatz und merken Sie sich, dass der Cache ungültig ist und daher aus der BLL bezogen wird, wenn die Daten erneut an die GridView gebunden werden.

Hinweis

Die Zwischenspeicherungsebene, die im Download bereitgestellt wird, der diesen Artikel begleitet, ist nicht vollständig. Es enthält nur eine Klasse, ProductsCL, die nur eine Handvoll Methoden besitzt. Darüber hinaus verwendet nur eine einzelne ASP.NET-Seite die CL (~/Caching/FromTheArchitecture.aspx), während alle anderen weiterhin direkt auf die BLL verweisen. Wenn Sie eine CL in Ihrer Anwendung verwenden möchten, sollten alle Aufrufe der Presentation Layer zur CL wechseln, was erfordern würde, dass die CL-Klassen und -Methoden diese Klassen und Methoden in der derzeit von der Presentation Layer verwendeten BLL behandelten.

Zusammenfassung

Während das Zwischenspeichern auf der Präsentationsebene mit den ASP.NET 2.0 SqlDataSource- und ObjectDataSource-Steuerelementen angewendet werden kann, sollten idealerweise die Zuständigkeiten für das Zwischenspeichern an eine separate Ebene in der Architektur delegiert werden. In diesem Lernprogramm haben wir eine Zwischenspeicherungsebene erstellt, die sich zwischen der Präsentationsschicht und der Geschäftslogikebene befindet. Die Caching-Ebene muss den gleichen Satz von Klassen und Methoden bereitstellen, die in der BLL vorhanden sind und von der Präsentationsebene aufgerufen werden.

Die Beispiele für den Caching-Layer, die wir in diesem und den vorherigen Tutorials untersucht haben, zeigten reaktives Laden. Bei reaktivem Laden werden die Daten nur dann in den Cache geladen, wenn eine Anforderung für die Daten erstellt wird und diese Daten im Cache fehlen. Daten können auch proaktiv in den Cache geladen werden, eine Technik, die die Daten in den Cache lädt, bevor sie tatsächlich benötigt wird. Im nächsten Lernprogramm sehen wir ein Beispiel für proaktives Laden, wenn wir uns ansehen, wie statische Werte beim Starten der Anwendung im Cache gespeichert werden.

Glückliche Programmierung!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.

Besonderer Dank an

Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitender Prüfer für dieses Lernprogramm war Teresa Murph. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.