Freigeben über


Zwischenspeichern von Daten in der Architektur (C#)

von Scott Mitchell

PDF herunterladen

Im vorherigen Tutorial haben wir gelernt, wie Sie das Zwischenspeichern auf der Präsentationsebene anwenden. In diesem Tutorial erfahren Sie, wie Sie unsere mehrschichtige Architektur nutzen, um Daten auf der Geschäftslogikebene zwischenzuspeichern. Dazu erweitern wir die Architektur um eine Cacheebene.

Einführung

Wie im vorherigen Tutorial gezeigt, ist das Zwischenspeichern der ObjectDataSource-Daten so einfach wie das Festlegen einiger Eigenschaften. Leider wendet ObjectDataSource die Zwischenspeicherung auf der Präsentationsebene an, wodurch die Zwischenspeicherungsrichtlinien eng mit der Seite ASP.NET gekoppelt werden. Einer der Gründe für die Erstellung einer mehrstufigen Architektur besteht darin, dass solche Kopplungen unterbrochen werden können. Die Geschäftslogikebene entkoppelt für instance die Geschäftslogik von den ASP.NET Seiten, während die Datenzugriffsebene die Datenzugriffsdetails entkoppelt. Diese Entkopplung von Geschäftslogik und Datenzugriffsdetails wird bevorzugt, zum Teil, weil sie das System lesbarer, verwaltbarer und flexibler für Änderungen macht. Es ermöglicht auch Domänenwissen und Arbeitsteilung, die ein Entwickler, der auf der Präsentationsebene arbeitet, nicht mit den Details der Datenbank vertraut sein muss, um seine Arbeit zu erledigen. Das Entkoppeln der Zwischenspeicherungsrichtlinie von der Präsentationsebene bietet ähnliche Vorteile.

In diesem Tutorial erweitern wir unsere Architektur, um eine Cacheebene (kurz CL) einzuschließen, die unsere Cacherichtlinie verwendet. Die Cacheebene enthält eine ProductsCL Klasse, die Zugriff auf Produktinformationen mit Methoden wie GetProducts(), GetProductsByCategoryID(categoryID)usw. ermöglicht, die beim Aufrufen zuerst versucht, die Daten aus dem Cache abzurufen. Wenn der Cache leer ist, rufen diese Methoden die entsprechende ProductsBLL Methode in der BLL auf, die wiederum die Daten aus dem DAL abrufen würde. Die ProductsCL Methoden speichern die aus der BLL abgerufenen Daten zwischen, bevor sie zurückgegeben werden.

Wie Abbildung 1 zeigt, befindet sich die CL zwischen der Präsentations- und der Geschäftslogikebene.

Die Cacheebene (CL) ist eine weitere Ebene in unserer Architektur.

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

Schritt 1: Erstellen der Zwischenspeicherebenenklassen

In diesem Tutorial erstellen wir eine sehr einfache CL mit einer einzelnen Klasse ProductsCL , die nur über eine Handvoll Methoden verfügt. Das Erstellen einer vollständigen Cacheebene für die gesamte Anwendung erfordert das Erstellen CategoriesCLvon , EmployeesCLund Klassen SuppliersCL sowie die Bereitstellung einer Methode in diesen Caching Layer-Klassen für jede Datenzugriffs- oder Änderungsmethode in der BLL. Wie bei BLL und DAL sollte die Cacheebene idealerweise als separates Klassenbibliotheksprojekt implementiert werden; Wir implementieren sie jedoch als Klasse im App_Code Ordner.

Um die CL-Klassen besser von den DAL- und BLL-Klassen zu trennen, erstellen sie einen neuen Unterordner im App_Code Ordner. Klicken Sie mit der rechten Maustaste auf den App_Code Ordner im Projektmappen-Explorer, wählen Sie Neuer Ordner aus, und nennen Sie den neuen Ordner CL. Nachdem Sie diesen Ordner erstellt haben, fügen Sie ihm eine neue Klasse mit dem Namen ProductsCL.cshinzu.

Hinzufügen eines neuen Ordners namens CL und einer Klasse namens ProductsCL.cs

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

Die ProductsCL -Klasse sollte denselben Satz von Datenzugriffs- und -änderungsmethoden wie in der entsprechenden Business Logic Layer-Klasse (ProductsBLL) enthalten. Anstatt alle diese Methoden zu erstellen, erstellen wir hier einfach ein paar, um ein Gefühl für die von der CL verwendeten Muster zu erhalten. Insbesondere fügen wir die GetProducts() Methoden und GetProductsByCategoryID(categoryID) in Schritt 3 und eine UpdateProduct Überladung in Schritt 4 hinzu. Sie können die verbleibenden ProductsCL Methoden und CategoriesCL, EmployeesCLund SuppliersCL Klassen nach Belieben hinzufügen.

Schritt 2: Lesen und Schreiben in den Datencache

Die im vorherigen Tutorial untersuchte ObjectDataSource-Zwischenspeicherung verwendet intern den ASP.NET Datencache, um die aus der BLL abgerufenen Daten zu speichern. Auf den Datencache kann auch programmgesteuert über ASP.NET CodeBehind-Klassen oder über die Klassen in der Architektur der Webanwendung zugegriffen werden. Verwenden Sie das folgende Muster, um aus einer CodeBehind-Klasse der ASP.NET Seite in den Datencache 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 s Insert der Klasse verfügt über eine Reihe von Überladungen. Cache["key"] = value und Cache.Insert(key, value) sind synonym, und beide fügen dem Cache ein Element mithilfe des angegebenen Schlüssels ohne definierten Ablauf hinzu. In der Regel möchten wir beim Hinzufügen eines Elements zum Cache einen Ablauf angeben, entweder als Abhängigkeit, als zeitbasiertes Ablaufdatum oder beides. Verwenden Sie eine der anderen Insert Methoden-s-Überladungen, um Abhängigkeits- oder zeitbasierte Ablaufinformationen bereitzustellen.

Die Cacheebenen-Methoden müssen zuerst überprüfen, ob sich die angeforderten Daten im Cache befinden, und wenn ja, sie 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 im folgenden Sequenzdiagramm dargestellt.

Die Methoden der Zwischenspeicherebene geben Daten aus dem Cache zurück, wenn diese verfügbar sind.

Abbildung 3: Die Methoden der Zwischenspeicherebene geben Daten aus dem Cache zurück, wenn diese verfügbar sind.

Die in Abbildung 3 dargestellte Sequenz wird in den CL-Klassen mit dem folgenden Muster ausgeführt:

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 key der Schlüssel ist, der das Cacheelement eindeutig identifiziert. Wenn sich das Element mit dem angegebenen Schlüssel nicht im Cache befindet, wird nullinstance, und die Daten werden von der entsprechenden BLL-Methode abgerufen und dem Cache hinzugefügt. Wenn der Zeitpunkt return instance erreicht ist, enthält instance einen Verweis auf die Daten, entweder aus dem Cache oder aus der BLL abgerufen.

Achten Sie darauf, dass Sie das obige Muster verwenden, wenn Sie auf Daten aus dem Cache zugreifen. Das folgende Muster, das auf den ersten Blick gleichwertig aussieht, enthält einen subtilen Unterschied, der eine Racebedingung einführt. Racebedingungen sind schwierig 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, auf den Datencache direkt in der bedingten Anweisung und in der returnzugegriffen wird. Stellen Sie sich vor, wenn dieser Code erreicht wird, Cache["key"] ist nicht,null aber bevor die return Anweisung erreicht wird, entfernt das System den Schlüssel aus dem Cache. In diesem seltenen Fall gibt der Code einen null Wert anstelle eines Objekts des erwarteten Typs zurück.

Hinweis

Der Datencache ist threadsicher, sodass Sie den Threadzugriff für einfache Lese- oder Schreibvorgänge nicht 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 zu gewährleisten. Weitere Informationen finden Sie unter Synchronisieren des Zugriffs auf den ASP.NET Cache .

Ein Element kann programmgesteuert aus dem Datencache entfernt werden, indem die Remove -Methode wie folgt verwendet wird:

Cache.Remove(key);

Schritt 3: Zurückgeben von Produktinformationen aus derProductsCLKlasse

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

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 DataObject Attribute und DataObjectMethodAttribute , die auf die Klasse und die Methoden angewendet werden. Diese Attribute stellen Dem ObjectDataSource-Assistenten Informationen zur Verfügung, die angeben, welche Klassen und Methoden in den Schritten des Assistenten angezeigt werden sollen. Da auf die CL-Klassen und -Methoden von einer ObjectDataSource in der Präsentationsebene aus zugegriffen wird, habe ich diese Attribute hinzugefügt, um die Entwurfszeiterfahrung zu verbessern. Eine ausführlichere Beschreibung dieser Attribute und ihrer Auswirkungen finden Sie im Tutorial Erstellen einer Geschäftslogikebene .

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

Die GetCacheItem(key) Methoden und AddCacheItem(key, value) sind mit dem Datencache zusammen und lesen bzw. schreiben Werte. Die GetCacheItem(key) -Methode ist die einfachere der beiden. Sie gibt einfach den Wert aus der Cache-Klasse mithilfe des übergebenen Schlüssels zurück:

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 wie angegeben den Schlüsselwert , sondern ruft stattdessen die GetCacheKey(key) -Methode auf, die den Schlüssel zurückgibt, dem ProductsCache- vorangestellt ist. Der MasterCacheKeyArray, der die Zeichenfolge ProductsCache enthält, wird auch von der AddCacheItem(key, value) -Methode verwendet, wie wir kurz sehen werden.

Von einer ASP.NET CodeBehind-Klasse der Seite aus kann auf den Datencache mit der Eigenschaft s Cacheder Page Klasse zugegriffen werden, und es ermöglicht Syntax wie Cache["key"] = value, wie in Schritt 2 erläutert. Über eine Klasse innerhalb der Architektur kann mit HttpRuntime.Cache oder HttpContext.Current.Cacheauf den Datencache zugegriffen werden. Peter Johnsons Blogeintrag HttpRuntime.Cache vs. HttpContext.Current.Cache weist auf den geringfügigen Leistungsvorteil bei der Verwendung HttpRuntime von anstelle von HttpContext.Currenthin. ProductsCLHttpRuntime

Hinweis

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

Wenn das Element nicht im Cache gefunden wird, rufen die Methoden der ProductsCL Klasse die Daten aus der BLL ab und fügen sie dem Cache mithilfe der AddCacheItem(key, value) -Methode hinzu. Um dem Cache einen Wert hinzuzufügen, können wir den folgenden Code verwenden, der einen Zeitablauf 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, und System.Web.Caching.Cache.NoSlidingExpiration gibt an, dass kein gleitender Ablauf vorliegt. Diese Insert Methodenüberladung verfügt zwar über Eingabeparameter sowohl für einen absoluten als auch für einen gleitenden Ablauf, Sie können jedoch nur einen der beiden angeben. Wenn Sie versuchen, sowohl eine absolute Zeit als auch eine Zeitspanne anzugeben, löst die Insert Methode eine Ausnahme aus ArgumentException .

Hinweis

Diese Implementierung der AddCacheItem(key, value) Methode weist derzeit einige Mängel auf. Diese Probleme werden in Schritt 4 behandelt und behoben.

Schritt 4: Ungültiger Cache, wenn die Daten über die Architektur geändert werden

Zusammen mit Den Methoden zum Abrufen von Daten muss die Cacheebene die gleichen Methoden wie die BLL zum Einfügen, Aktualisieren und Löschen von Daten bereitstellen. Die Datenänderungsmethoden der CL ändern nicht die zwischengespeicherten Daten, sondern rufen stattdessen die entsprechende Datenänderungsmethode der BLL auf, und dann wird der Cache ungültig. Wie wir im vorherigen Tutorial gesehen haben, ist dies dasselbe Verhalten, das objectDataSource anwendet, wenn die Zwischenspeicherungsfeatures aktiviert sind und die InsertMethoden , Updateoder Delete 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 Datenänderungs-Business Logic Layer-Methode wird aufgerufen, aber bevor die Antwort zurückgegeben wird, müssen wir den Cache für ungültig erklären. Leider ist es nicht einfach, den Cache für ungültig zu erklären, da die ProductsCL Klassen und GetProducts()GetProductsByCategoryID(categoryID) Methoden jeweils Elemente mit unterschiedlichen Schlüsseln zum Cache hinzufügen und die GetProductsByCategoryID(categoryID) -Methode für jede eindeutige CategoryID ein anderes Cacheelement hinzufügt.

Wenn sie den Cache ungültig machen, müssen wir alle Elemente entfernen, die möglicherweise von der ProductsCL -Klasse hinzugefügt wurden. Dies kann durch Zuordnen einer Cacheabhängigkeit zu den einzelnen Elementen erreicht werden, 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 Cacheelemente, denen sie zugeordnet ist, automatisch aus dem Cache entfernt. In diesem Tutorial 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 werden. Auf diese Weise können alle diese Elemente aus dem Cache entfernt werden, indem einfach die Cacheabhängigkeit entfernt wird.

Aktualisieren Sie die AddCacheItem(key, value) -Methode, sodass 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 CacheDependency Konstruktor der Klasse s verfügt über eine Reihe von Überladungen, aber der hier verwendete Konstruktor erwartet zwei string Arrayeingaben. Die 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 der Wert verwendet null . 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 Wird CacheDependency dann an die Insert -Methode übergeben.

Mit dieser Änderung von AddCacheItem(key, value)ist das Ungültigen 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 Zwischenspeicherebene von der Präsentationsebene

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

Die ProductsCL-Klasse ist in der Liste

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

Nachdem Sie ausgewählt haben ProductsCL, klicken Sie auf Weiter. Die Dropdownliste auf der Registerkarte SELECT enthält zwei Elemente – GetProducts() und GetProductsByCategoryID(categoryID) die Registerkarte UPDATE hat die einzige UpdateProduct Überladung. Wählen Sie auf der Registerkarte SELECT die GetProducts() Methode und die UpdateProducts Methode auf der Registerkarte UPDATE aus, und klicken Sie auf Fertig stellen.

Die Methoden der ProductsCL-Klasse sind im Drop-Down Listen

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

Nach Abschluss des Assistenten legt Visual Studio die ObjectDataSource-Eigenschaft OldValuesParameterFormatString auf fest original_{0} und fügt der GridView die entsprechenden Felder hinzu. Ändern Sie die OldValuesParameterFormatString Eigenschaft wieder auf ihren Standardwert , {0}und konfigurieren Sie gridView so, dass Paging, Sortierung und Bearbeitung unterstützt wird. Da die UploadProducts von der CL verwendete Überladung nur den Namen und preis des bearbeiteten Produkts akzeptiert, beschränken Sie gridView so, dass nur diese Felder bearbeitbar sind.

Im vorherigen Tutorial haben wir ein GridView-Objekt definiert, das Felder für die ProductNameFelder , CategoryNameund UnitPrice enthält. Sie können diese Formatierung und Struktur replizieren. In diesem Fall sollte Das deklarative Markup von GridView und ObjectDataSource in etwa 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 verfügen wir über eine Seite, die die Cacheebene verwendet. Um den Cache in Aktion zu sehen, legen Sie Haltepunkte in den ProductsCL Klassen s 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 beachten Sie, dass der Cache ungültig ist und folglich aus der BLL abgerufen wird, wenn die Daten an GridView rebound werden.

Hinweis

Die im Download zu diesem Artikel bereitgestellte Cacheebene ist nicht vollständig. Es enthält nur eine Klasse, ProductsCL, die nur eine Handvoll Methoden verwendet. Darüber hinaus verwendet nur eine einzelne ASP.NET Seite die CL (~/Caching/FromTheArchitecture.aspx), die alle anderen weiterhin direkt auf die BLL verweisen. Wenn Sie planen, eine CL in Ihrer Anwendung zu verwenden, sollten alle Aufrufe von der Präsentationsebene an die CL gehen. Dies erfordert, dass die Klassen und Methoden der CL diese Klassen und Methoden in der derzeit von der Präsentationsebene verwendeten BLL abdecken.

Zusammenfassung

Während das Zwischenspeichern auf der Präsentationsebene mit ASP.NET SqlDataSource- und ObjectDataSource-Steuerelementen von ASP.NET 2.0 s angewendet werden kann, werden Zuständigkeiten im Idealfall an eine separate Ebene in der Architektur delegiert. In diesem Tutorial haben wir eine Zwischenspeicherungsebene erstellt, die sich zwischen der Präsentationsebene und der Geschäftslogikebene befindet. Die Cacheebene 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 die Cachingebene, die wir in diesem und den vorherigen Tutorials untersucht haben, zeigen reaktives Laden. Beim reaktiven Laden werden die Daten nur dann in den Cache geladen, wenn eine Anforderung für die Daten erfolgt und diese Daten im Cache fehlen. Daten können auch proaktiv in den Cache geladen werden, eine Technik, bei der die Daten in den Cache geladen werden, bevor sie tatsächlich benötigt werden. Im nächsten Tutorial sehen wir uns ein Beispiel für proaktives Laden an, wenn wir uns ansehen, wie statische Werte beim Anwendungsstart im Cache gespeichert werden.

Viel Spaß beim Programmieren!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderer Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüferin für dieses Tutorial war Teresa Murph. Möchten Sie meine bevorstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.