Udostępnij za pośrednictwem


Buforowanie danych w architekturze (C#)

Autor : Scott Mitchell

Pobierz plik PDF

W poprzednim samouczku dowiedzieliśmy się, jak zastosować buforowanie w warstwie prezentacji. Z tego samouczka dowiesz się, jak korzystać z naszej architektury warstwowej w celu buforowania danych w warstwie logiki biznesowej. W tym celu rozszerzymy architekturę tak, aby zawierała warstwę buforowania.

Wprowadzenie

Jak pokazano w poprzednim samouczku, buforowanie danych ObjectDataSource jest tak proste, jak ustawienie kilku właściwości. Niestety obiekt ObjectDataSource stosuje buforowanie w warstwie prezentacji, która ściśle łączy zasady buforowania ze stroną ASP.NET. Jedną z przyczyn tworzenia architektury warstwowej jest umożliwienie zerwania takich sprzężeń. Warstwa logiki biznesowej, na przykład, rozdziela logikę biznesową ze stron ASP.NET, podczas gdy warstwa dostępu do danych rozdziela szczegóły dostępu do danych. To oddzielenie logiki biznesowej i szczegółów dostępu do danych jest preferowane, między innymi dlatego, że system staje się bardziej czytelny, łatwiejszy w utrzymaniu i bardziej elastyczny w przypadku zmian. Pozwala to również na wiedzę o domenie i podział pracy deweloper pracujący nad warstwą prezentacji nie musi być zaznajomiony ze szczegółami bazy danych, aby wykonać swoją pracę. Oddzielenie zasad buforowania z warstwy prezentacji oferuje podobne korzyści.

W tym samouczku rozszerzymy naszą architekturę tak, aby zawierała warstwę buforowania (lub cl w skrócie), która wykorzystuje nasze zasady buforowania. Warstwa buforowania będzie zawierać klasę ProductsCL, która zapewnia dostęp do informacji o produkcie za pomocą takich metod jak GetProducts(), GetProductsByCategoryID(categoryID) i inne, które po wywołaniu najpierw spróbują pobrać dane z pamięci podręcznej. Jeśli pamięć podręczna jest pusta, te metody wywołają odpowiednią ProductsBLL metodę w warstwie BLL, co z kolei spowoduje pobranie danych z DAL. Metody ProductsCL buforuje dane pobrane z usługi BLL przed ich zwróceniem.

Jak pokazano na rysunku 1, cl znajduje się między warstwami prezentacji i logiki biznesowej.

Warstwa buforowania (CL) to kolejna warstwa w naszej architekturze

Rysunek 1. Warstwa buforowania (CL) to kolejna warstwa w naszej architekturze

Krok 1. Tworzenie klas warstw buforowania

W tym samouczku utworzymy bardzo prostą cl z pojedynczą klasą ProductsCL , która ma tylko kilka metod. Utworzenie pełnej warstwy buforowania dla całej aplikacji wymagałoby utworzenia klas CategoriesCL, EmployeesCL i SuppliersCL oraz zapewnienia metod w tych klasach warstwy buforowania dla każdej metody dostępu do danych lub modyfikacji w warstwie logiki biznesowej (BLL). Podobnie jak w przypadku bibliotek BLL i DAL, warstwa buforowania najlepiej byłaby zaimplementowana jako osobny projekt biblioteka klas; jednak zaimplementujemy ją jako klasę w folderze App_Code.

Aby dokładniej oddzielić klasy CL od klas DAL i BLL, utwórzmy nowy podfolder w folderze App_Code . Kliknij prawym przyciskiem myszy App_Code folder w Eksploratorze rozwiązań, wybierz pozycję Nowy folder i nazwij nowy folder CL. Po utworzeniu tego folderu dodaj do niego nową klasę o nazwie ProductsCL.cs.

Dodawanie nowego folderu o nazwie CL i klasy o nazwie ProductsCL.cs

Rysunek 2. Dodawanie nowego folderu o nazwie CL i klasy o nazwie ProductsCL.cs

Klasa ProductsCL powinna zawierać ten sam zestaw metod dostępu do danych i modyfikacji, co w odpowiedniej klasie warstwy logiki biznesowej (ProductsBLL). Zamiast tworzyć wszystkie te metody, po prostu skompilujmy kilka tutaj, aby poczuć wzorce używane przez CL. W szczególności dodamy metody GetProducts() i GetProductsByCategoryID(categoryID) w kroku 3 oraz przeciążenie UpdateProduct w kroku 4. Pozostałe metody ProductsCL oraz klasy CategoriesCL, EmployeesCL i SuppliersCL można dodawać w wolnym czasie.

Krok 2. Odczytywanie i zapisywanie w pamięci podręcznej danych

Funkcja buforowania ObjectDataSource eksplorowana w poprzednim samouczku wewnętrznie używa pamięci podręcznej danych ASP.NET do przechowywania danych pobranych z biblioteki BLL. Dostęp do pamięci podręcznej danych można również uzyskać programowo z klas kodu zaplecza stron ASP.NET lub z klas w architekturze aplikacji internetowej. Aby odczytywać i zapisywać dane w pamięci podręcznej klasy code-behind strony ASP.NET, użyj następującego wzorca:

// 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);

Metoda Cache klasy Insert ma wiele przeciążeń. Cache["key"] = value i Cache.Insert(key, value) są synonimami, a oba dodają element do pamięci podręcznej przy użyciu określonego klucza bez zdefiniowanego wygaśnięcia. Zazwyczaj chcemy określić wygaśnięcie przy dodawaniu elementu do pamięci podręcznej, albo jako zależność, albo jako wygaśnięcie zależne od czasu, albo oba jednocześnie. Użyj jednego z innych Insert przeciążeń metody, aby zapewnić zależności lub informacje o wygaśnięciu na podstawie czasu.

Metody warstwy buforowania muszą najpierw sprawdzić, czy żądane dane znajdują się w pamięci podręcznej, a jeśli tak, to je stamtąd zwrócić. Jeśli żądane dane nie są w pamięci podręcznej, należy wywołać odpowiednią metodę BLL. Jego wartość zwracana powinna być buforowana, a następnie zwracana, jak pokazano na poniższym diagramie sekwencji.

Metody warstwy buforowania zwracają dane z pamięci podręcznej, jeśli są dostępne

Rysunek 3. Metody warstwy buforowania zwracają dane z pamięci podręcznej, jeśli są dostępne

Sekwencja przedstawiona na rysunku 3 jest realizowana w klasach CL przy użyciu następującego wzorca:

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

Tutaj typ to typ danych przechowywanych w pamięci podręcznej Northwind.ProductsDataTable, na przykład klucz jest kluczem, który jednoznacznie identyfikuje element pamięci podręcznej. Jeśli element o określonym kluczu nie znajduje się w pamięci podręcznej, wystąpienie będzie null i dane zostaną pobrane z odpowiedniej metody BLL i dodane do pamięci podręcznej. Po osiągnięciu punktu return instance, instancja zawiera odwołanie do danych, pochodzące z pamięci podręcznej lub pobrane z usługi BLL.

Pamiętaj, aby użyć powyższego wzorca podczas uzyskiwania dostępu do danych z pamięci podręcznej. Poniższy wzorzec, który na pierwszy rzut oka wygląda równoważnie, zawiera subtelną różnicę, która wprowadza warunek wyścigu. Warunki wyścigu są trudne do debugowania, ponieważ ujawniają się sporadycznie i są trudne do odtworzenia.

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

Różnica w tym drugim, niepoprawnym fragmencie kodu polega na tym, że zamiast przechowywać odwołanie do buforowanego elementu w zmiennej lokalnej, dostęp do pamięci podręcznej danych jest uzyskiwany bezpośrednio w instrukcji warunkowej i w elemencie return. Wyobraź sobie, że kiedy ten kod zostanie osiągnięty, Cache["key"] nie jest null, ale zanim osiągnięta zostanie instrukcja return, system eksmituje klucz z pamięci podręcznej. W tym rzadkim przypadku kod zwróci null wartość, a nie obiekt oczekiwanego typu.

Uwaga / Notatka

Pamięć podręczna danych jest bezpieczna dla wątków, więc nie trzeba synchronizować dostępów wątków do prostych operacji odczytu lub zapisu. Jeśli jednak musisz wykonać wiele operacji na danych w pamięci podręcznej, które muszą być atomowe, odpowiadasz za zaimplementowanie blokady lub innego mechanizmu w celu zapewnienia bezpieczeństwa współbieżności. Aby uzyskać więcej informacji, zobacz Synchronizowanie dostępu do pamięci podręcznej ASP.NET.

Element można eksmitować programowo z pamięci podręcznej danych przy użyciu Remove metody w następujący sposób:

Cache.Remove(key);

Krok 3: Zwracanie informacji o produkcieProductsCLz klasy

Na potrzeby tego samouczka zaimplementujmy dwie metody zwracania informacji o produkcie ProductsCL z klasy: GetProducts() i GetProductsByCategoryID(categoryID). Podobnie jak w przypadku ProductsBL klasy w warstwie logiki biznesowej metoda GetProducts() w cl zwraca informacje o wszystkich produktach jako Northwind.ProductsDataTable obiekcie, a jednocześnie GetProductsByCategoryID(categoryID) zwraca wszystkie produkty z określonej kategorii.

Poniższy kod przedstawia część metod w ProductsCL klasie:

[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;
        }
    }
}

Najpierw zwróć uwagę na atrybuty DataObject i DataObjectMethodAttribute oraz ich zastosowanie w klasie i metodach. Te atrybuty dostarczają informacji do kreatora ObjectDataSource, określając, jakie klasy i metody powinny być uwzględnione w krokach kreatora. Ponieważ klasy i metody CL będą dostępne z obiektu ObjectDataSource w warstwie prezentacji, dodałem te atrybuty, aby ulepszyć środowisko projektowania w czasie projektowania. Zapoznaj się z samouczkiem Tworzenie warstwy logiki biznesowej , aby uzyskać bardziej szczegółowy opis tych atrybutów i ich wpływu.

W metodach GetProducts() i GetProductsByCategoryID(categoryID), dane zwrócone z metody GetCacheItem(key) są przypisane do zmiennej lokalnej. Metoda GetCacheItem(key) , którą wkrótce zbadamy, zwraca określony element z pamięci podręcznej na podstawie określonego klucza. Jeśli takie dane nie zostaną znalezione w pamięci podręcznej, zostaną pobrane z odpowiedniej ProductsBLL metody klasy, a następnie dodane do pamięci podręcznej przy użyciu AddCacheItem(key, value) metody .

Metody GetCacheItem(key) i AddCacheItem(key, value) interfejsują z pamięcią podręczną danych, odpowiednio odczytując i zapisując wartości. Metoda GetCacheItem(key) jest prostsza z tych dwóch. Po prostu zwraca wartość z klasy Cache przy użyciu przekazanego klucza:

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) nie używa wartości klucza zgodnie z podaną wartością, ale zamiast tego wywołuje metodę GetCacheKey(key) która zwraca klucz z prefiksem ProductsCache-. Element MasterCacheKeyArray, który przechowuje ciąg ProductsCache, jest również używany przez metodę AddCacheItem(key, value) , ponieważ zobaczymy to chwilowo.

Z klasy ASP.NET w kodzie obsługi można uzyskać dostęp do pamięci podręcznej danych za pomocą właściwości klasy Page, co umożliwia składnię, na przykład Cache, zgodnie z opisem w kroku 2. Z klasy w ramach architektury można uzyskać dostęp do pamięci podręcznej danych przy użyciu metody HttpRuntime.Cache lub HttpContext.Current.Cache. Wpis w blogu Petera JohnsonaHttpRuntime.Cache vs. HttpContext.Current.Cache zauważa niewielką przewagę wydajności w użyciu HttpRuntime zamiast HttpContext.Current; w związku z tym ProductsCL używa HttpRuntime.

Uwaga / Notatka

Jeśli architektura jest implementowana przy użyciu projektów biblioteki klas, należy dodać odwołanie do System.Web zestawu, aby używać klas HttpRuntime i HttpContext .

Jeśli element nie zostanie znaleziony w pamięci podręcznej, ProductsCL metody klasy pobierają dane z biblioteki BLL i dodają je do pamięci podręcznej przy użyciu AddCacheItem(key, value) metody . Aby dodać wartość do pamięci podręcznej, możemy użyć następującego kodu, który wygasa po 60 sekundach.

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) określa, że wygasa po 60 sekundach, podczas gdy System.Web.Caching.Cache.NoSlidingExpiration wskazuje, że nie ma przesunięcia terminu wygaśnięcia. Chociaż przeciążenie metody Insert posiada parametry wejściowe zarówno dla wygaśnięcia stałego, jak i przesuwanego, można podać tylko jeden z nich. Jeśli spróbujesz określić zarówno bezwzględny czas, jak i przedział czasu, Insert metoda zgłosi ArgumentException wyjątek.

Uwaga / Notatka

Ta implementacja AddCacheItem(key, value) metody obecnie ma pewne wady. Rozwiążemy te problemy i rozwiążemy je w kroku 4.

Krok 4. Unieważnienie pamięci podręcznej po zmodyfikowaniu danych za pomocą architektury

Oprócz metod pobierania danych warstwa buforowania musi zapewnić takie same metody jak BLL do wstawiania, aktualizowania i usuwania danych. Metody modyfikacji danych CL nie modyfikują buforowanych danych, a zamiast tego wywołują odpowiednią metodę modyfikacji danych BLL, a następnie unieważniają ją. Jak pokazano w poprzednim samouczku, jest to to samo zachowanie, które stosuje ObjectDataSource, gdy jego funkcje buforowania są włączone i gdy jego metody Insert, Update lub Delete są wywoływane.

Następujące UpdateProduct przeciążenie ilustruje sposób implementowania metod modyfikacji danych w CL:

[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;
}

Wywoływana jest metoda warstwy logiki biznesowej do modyfikacji danych, ale zanim jej odpowiedź zostanie zwrócona, musimy unieważnić cache. Niestety, unieważnienie pamięci podręcznej nie jest proste, ponieważ klasa ProductsCL oraz metody GetProducts() i GetProductsByCategoryID(categoryID) dodają elementy do pamięci podręcznej z różnymi kluczami, a metoda GetProductsByCategoryID(categoryID) dodaje inny element pamięci podręcznej dla każdego unikalnego identyfikatora kategorii.

Podczas unieważniania pamięci podręcznej musimy usunąć wszystkie elementy, które mogły zostać dodane przez klasę ProductsCL . Można to osiągnąć przez skojarzenie zależności pamięci podręcznej z każdym elementem dodanym do pamięci podręcznej w metodzie AddCacheItem(key, value) . Ogólnie rzecz biorąc, zależność pamięci podręcznej może być innym elementem w pamięci podręcznej, plikiem w systemie plików lub danymi z bazy danych programu Microsoft SQL Server. Gdy zależność ulegnie zmianie lub zostanie usunięta z pamięci podręcznej, elementy pamięci podręcznej, z których jest skojarzona, są automatycznie eksmitowane z pamięci podręcznej. W tym samouczku chcemy utworzyć dodatkowy element w pamięci podręcznej, który służy jako zależność pamięci podręcznej dla wszystkich elementów dodanych przez klasę ProductsCL. Dzięki temu wszystkie te elementy można usunąć z pamięci podręcznej, usuwając po prostu zależność pamięci podręcznej.

Zaktualizujmy metodę AddCacheItem(key, value) tak, aby każdy element dodany do pamięci podręcznej za pomocą tej metody był skojarzony z jedną zależnością pamięci podręcznej:

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 to tablica ciągów zawierająca pojedynczą wartość ProductsCache. Najpierw element pamięci podręcznej jest dodawany do pamięci podręcznej i przypisany do bieżącej daty i godziny. Jeśli element pamięci podręcznej już istnieje, zostanie zaktualizowany. Następnie zostanie utworzona zależność pamięci podręcznej. Konstruktor CacheDependency klasy ma wiele przeciążeń, ale w tym przypadku oczekuje dwóch string tablic wejściowych. Pierwszy określa zestaw plików, które mają być używane jako zależności. Ponieważ nie chcemy używać żadnych zależności opartych na plikach, wartość null jest używana dla pierwszego parametru wejściowego. Drugi parametr wejściowy określa zestaw kluczy pamięci podręcznej do użycia jako zależności. W tym miejscu określamy naszą pojedynczą zależność. MasterCacheKeyArray Element CacheDependency jest następnie przekazywany do Insert metody .

W tej modyfikacji AddCacheItem(key, value), unieważnienie pamięci podręcznej jest tak proste jak usunięcie zależności.

[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]);
}

Krok 5. Wywoływanie warstwy buforowania z warstwy prezentacji

Klasy i metody warstwy buforowania mogą służyć do pracy z danymi przy użyciu technik, które omówiliśmy w tych samouczkach. Aby zilustrować pracę z danymi w pamięci podręcznej, zapisz zmiany w ProductsCL klasie, a następnie otwórz FromTheArchitecture.aspx stronę w folderze Caching i dodaj kontrolkę GridView. Na podstawie tagu inteligentnego GridView utwórz nowy obiekt ObjectDataSource. W pierwszym kroku kreatora powinna zostać wyświetlona ProductsCL klasa jako jedna z dostępnych opcji na liście rozwijanej.

Klasa ProductsCL znajduje się na liście obiektów biznesowych Drop-Down

Rysunek 4.ProductsCL Klasa jest uwzględniona na liście obiektów biznesowych Drop-Down (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po wybraniu ProductsCL kliknij przycisk Dalej. Lista rozwijana na karcie SELECT zawiera dwa elementy, GetProducts() i GetProductsByCategoryID(categoryID). Karta UPDATE ma jedno przeciążenie UpdateProduct. Wybierz metodę GetProducts() na karcie SELECT i UpdateProducts metodę na karcie UPDATE, a następnie kliknij przycisk Zakończ.

Metody klasy ProductsCL są wymienione na listach Drop-Down

Rysunek 5. ProductsCL Metody klas są wyświetlane na listach Drop-Down (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po zakończeniu działania kreatora, program Visual Studio ustawi właściwość ObjectDataSource na OldValuesParameterFormatStringoriginal_{0} i doda odpowiednie pola do kontrolki GridView. OldValuesParameterFormatString Zmień właściwość z powrotem na wartość domyślną, {0}i skonfiguruj element GridView, aby obsługiwał stronicowanie, sortowanie i edytowanie. Ponieważ przeciążenie używane przez CL akceptuje tylko edytowaną nazwę i cenę produktu, ogranicz GridView, aby tylko te pola były edytowalne.

W poprzednim samouczku zdefiniowaliśmy element GridView, aby uwzględnić pola dla ProductName, CategoryName i UnitPrice. Możesz zreplikować to formatowanie i strukturę. W takim przypadku znacznik deklaratywny GridView i ObjectDataSource powinien wyglądać podobnie do następującego:

<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>

W tym momencie mamy stronę korzystającą z warstwy buforowania. Aby zobaczyć pamięć podręczną w akcji, ustaw punkty przerwania w klasie ProductsCL oraz metodach GetProducts()UpdateProduct. Odwiedź stronę w przeglądarce i przejdź przez kod podczas sortowania i stronicowania, aby zobaczyć dane pobierane z pamięci podręcznej. Następnie zaktualizuj rekord i zwróć uwagę, że pamięć podręczna jest unieważniona, a w związku z tym jest pobierana z usługi BLL, gdy dane są przywracane do kontrolki GridView.

Uwaga / Notatka

Warstwa cache dostarczona w pobraniu wraz z tym artykułem nie jest kompletna. Zawiera tylko jedną klasę , ProductsCLktóra obsługuje tylko kilka metod. Co więcej, tylko jedna strona ASP.NET używa cl (~/Caching/FromTheArchitecture.aspx) wszystkie inne nadal odwołują się bezpośrednio do BLL. Jeśli planujesz użycie CL w swojej aplikacji, wszystkie wywołania z warstwy prezentacji powinny trafiać do CL, co wymagałoby, aby klasy i metody CL objęły te, które są obecnie używane w warstwie prezentacji przez BLL.

Podsumowanie

Buforowanie można stosować w warstwie prezentacji z kontrolkami SqlDataSource i ObjectDataSource ASP.NET 2.0 s, dlatego w idealnym przypadku obowiązki buforowania byłyby delegowane do oddzielnej warstwy w architekturze. W tym samouczku utworzyliśmy warstwę buforowania, która znajduje się między warstwą prezentacji a warstwą logiki biznesowej. Warstwa buforowania musi zapewnić ten sam zestaw klas i metod, które istnieją w warstwie logiki biznesowej (BLL) i są wywoływane przez warstwę prezentacji.

Przykłady warstwy buforowania, które zbadaliśmy w tym i poprzednich samouczkach, wykazały reaktywne ładowanie. W przypadku reaktywnego ładowania dane są ładowane do pamięci podręcznej tylko wtedy, gdy występuje żądanie danych, a dane te nie znajdują się w pamięci podręcznej. Dane mogą być również aktywnie ładowane do pamięci podręcznej— technika, która ładuje dane do pamięci podręcznej, zanim będzie ona rzeczywiście potrzebna. W następnym samouczku zobaczymy przykład proaktywnego ładowania, gdy przyjrzymy się, jak przechowywać wartości statyczne w pamięci podręcznej podczas uruchamiania aplikacji.

Szczęśliwe programowanie!

Informacje o autorze

Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w ciągu 24 godzin. Można go uzyskać pod adresem mitchell@4GuysFromRolla.com.

Specjalne podziękowania

Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Główny recenzent tego samouczka to Teresa Murph. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, napisz do mnie na adres mitchell@4GuysFromRolla.com.