Buforowanie danych w architekturze (C#)

Autor : Scott Mitchell

Pobierz plik PDF

W poprzednim samouczku przedstawiono sposób stosowania buforowania w warstwie prezentacji. Z tego samouczka dowiesz się, jak wykorzystać naszą architekturę warstwową do buforowania danych w warstwie logiki biznesowej. W tym celu rozszerzamy architekturę tak, aby zawierała warstwę buforowania.

Wprowadzenie

Jak pokazano w poprzednim samouczku, buforowanie danych obiektuDataSource 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. Jednym z powodów 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 szczegółów logiki biznesowej i dostępu do danych jest preferowane, po części dlatego, że system jest bardziej czytelny, bardziej czytelny i bardziej elastyczny do zmiany. Umożliwia to również wiedzę na temat domeny i podział pracy dewelopera pracującego 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 na krótko), która wykorzystuje nasze zasady buforowania. Warstwa buforowania będzie zawierać klasę ProductsCL , która zapewnia dostęp do informacji o produkcie za pomocą metod takich jak GetProducts(), GetProductsByCategoryID(categoryID)i tak dalej, że podczas wywoływanej metody najpierw spróbuje pobrać dane z pamięci podręcznej. Jeśli pamięć podręczna jest pusta, te metody wywołają odpowiednią ProductsBLL metodę w usłudze BLL, która z kolei pobierze dane z dal. Metody ProductsCL buforuje dane pobrane z BLL przed zwróceniem ich.

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 jedną klasą ProductsCL , która ma tylko kilka metod. Utworzenie pełnej warstwy buforowania dla całej aplikacji wymagałoby utworzenia CategoriesCLklas , EmployeesCLi SuppliersCL i udostępnienia metody w tych klasach warstwy buforowania dla każdej metody dostępu do danych lub modyfikacji w usłudze BLL. Podobnie jak w przypadku BLL i DAL, warstwa buforowania powinna być idealnie zaimplementowana jako oddzielny projekt biblioteki klas; jednak zaimplementujemy go 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 Eksplorator rozwiązań, wybierz pozycję Nowy folder i nazwij nowy folder CL. Po utworzeniu tego folderu dodaj do niego nową klasę o nazwie ProductsCL.cs.

Dodaj nowy folder o nazwie CL i klasę 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, skompilujmy tu parę, aby poczuć wzorce używane przez CL. W szczególności dodamy GetProducts() metody i GetProductsByCategoryID(categoryID) w kroku 3 i UpdateProduct przeciążenie w kroku 4. Pozostałe metody i CategoriesCLklasy , EmployeesCLi SuppliersCL można dodawać ProductsCL w czasie wolnym.

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

Funkcja buforowania ObjectDataSource omówiona 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 poziomu ASP.NET stron klasy kodu lub klas w architekturze aplikacji internetowej. Aby odczytywać i zapisywać w pamięci podręcznej danych z klasy kodowej 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 ma Insert 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 podczas dodawania elementu do pamięci podręcznej, albo jako zależności, wygaśnięcia na podstawie czasu lub obu tych elementów. Użyj jednego z innych Insert przeciążeń metody, aby zapewnić informacje o wygasaniu zależności lub czasu.

Metody warstwy buforowania muszą najpierw sprawdzić, czy żądane dane znajdują się w pamięci podręcznej, a jeśli tak, zwracają je stamtąd. 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 z określonym kluczem nie znajduje się w pamięci podręcznej , wystąpienie będzienull i dane zostaną pobrane z odpowiedniej metody BLL i dodane do pamięci podręcznej. Po osiągnięciu tego czasu return instancewystąpienie zawiera odwołanie do danych 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, pamięć podręczna danych jest dostępna bezpośrednio w instrukcji warunkowej i w return. Załóżmy, że gdy ten kod zostanie osiągnięty, Cache["key"] nie zostanienull osiągnięty, ale przed return osiągnięciem instrukcji system eksmituje klucz z pamięci podręcznej. W tym rzadkim przypadku kod zwróci null wartość, a nie obiekt oczekiwanego typu.

Uwaga

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

Element można programowo eksmitować 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

W tym samouczku zaimplementujmy dwie metody zwracania informacji o produkcie ProductsCL z klasy : GetProducts() i GetProductsByCategoryID(categoryID). Podobnie jak w przypadku ProductsBL klasy w warstwie logiki biznesowej, GetProducts() metoda w CL zwraca informacje o wszystkich produktach jako Northwind.ProductsDataTable obiekt, 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 zanotuj DataObject atrybuty i DataObjectMethodAttribute zastosowane do klasy i metod. Te atrybuty udostępniają informacje kreatora ObjectDataSource, wskazując, jakie klasy i metody powinny być wyświetlane w krokach kreatora. Ponieważ klasy i metody CL będą dostępne z obiektu ObjectDataSource w warstwie prezentacji, dodałem te atrybuty, aby poprawić ś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.

GetProducts() W metodach i GetProductsByCategoryID(categoryID) dane zwrócone z GetCacheItem(key) metody są przypisywane 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) interfejs z pamięcią podręczną danych, odczytywanie i zapisywanie wartości, odpowiednio. 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 jako podanej, ale zamiast tego wywołuje metodę GetCacheKey(key) , która zwraca klucz dołączony do elementu 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 s code-behind można uzyskać dostęp do pamięci podręcznej danych przy użyciu Page właściwości klasy Cachei umożliwia składnię, na przykład Cache["key"] = value, 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 ; w związku ProductsCL z HttpContext.Currenttym używa elementu HttpRuntime.

Uwaga

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 używa 60-sekundowego wygaśnięcia:

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 czas wygaśnięcia 60 sekund w przyszłości, a jednocześnie System.Web.Caching.Cache.NoSlidingExpiration wskazuje, że nie ma przesuwanego wygaśnięcia. Chociaż to Insert przeciążenie metody ma parametry wejściowe zarówno dla bezwzględnego, jak i przesuwanego wygaśnięcia, można podać tylko jeden z tych dwóch. Jeśli spróbujesz określić zarówno bezwzględny czas, jak i przedział czasu, Insert metoda zgłosi ArgumentException wyjątek.

Uwaga

Ta implementacja AddCacheItem(key, value) metody ma obecnie 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 s nie modyfikują danych buforowanych, ale raczej wywołają odpowiednią metodę modyfikacji danych BLL, a następnie unieważniają pamięć podręczną. Jak pokazano w poprzednim samouczku, jest to to samo zachowanie, które obiekt ObjectDataSource stosuje, gdy jego funkcje buforowania są włączone, a jej Insertmetody , Updatelub 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 odpowiednia metoda warstwy logiki biznesowej modyfikacji danych, ale zanim zostanie zwrócona jego odpowiedź, musimy unieważnić pamięć podręczną. Niestety unieważnienie pamięci podręcznej nie jest proste, ponieważ ProductsCL klasy s GetProducts() i GetProductsByCategoryID(categoryID) metody dodawania elementów do pamięci podręcznej z różnymi kluczami, a GetProductsByCategoryID(categoryID) metoda dodaje inny element pamięci podręcznej dla każdego unikatowego 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 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 . W ten sposób wszystkie te elementy można usunąć z pamięci podręcznej, usuwając po prostu zależność pamięci podręcznej.

Zaktualizujmy metodę tak AddCacheItem(key, value) , 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 jedną 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. CacheDependency Konstruktor klasy ma wiele przeciążeń, ale używany w tym miejscu oczekuje dwóch string danych wejściowych tablicy. 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ść parametru 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 przypadku tej modyfikacji w systemie 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 przeanalizowaliśmy w ramach tych samouczków. Aby zilustrować pracę z danymi w pamięci podręcznej, zapisz zmiany ProductsCL w klasie, a następnie otwórz FromTheArchitecture.aspx stronę w Caching folderze i dodaj element GridView. Na podstawie tagu inteligentnego GridView utwórz nowy obiektDataSource. W pierwszym kroku kreatora powinna zostać wyświetlona ProductsCL klasa jako jedna z opcji z listy rozwijanej.

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

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

Po wybraniu ProductsCLpozycji kliknij przycisk Dalej. Lista rozwijana na karcie SELECT zawiera dwa elementy — GetProducts() a GetProductsByCategoryID(categoryID) karta UPDATE ma jedyne UpdateProduct przeciążenie. Wybierz metodę GetProducts() z karty SELECT i UpdateProducts metodę z karty UPDATE i kliknij przycisk Zakończ.

Metody klasy ProductsCL są wymienione w Drop-Down Listy

Rysunek 5. ProductsCL Metody klasy są wymienione w Drop-Down Listy (kliknij, aby wyświetlić obraz pełnowymiarowy)

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

W poprzednim samouczku zdefiniowaliśmy element GridView, aby uwzględnić pola dla ProductNamepól , CategoryNamei UnitPrice . Możesz replikować to formatowanie i strukturę. W takim przypadku znaczniki deklaratywne GridView i ObjectDataSource powinny wyglądać podobnie do następujących:

<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ę, która używa warstwy buforowania. Aby wyświetlić pamięć podręczną w akcji, ustaw punkty przerwania w ProductsCL klasach s GetProducts() i UpdateProduct metodach. Odwiedź stronę w przeglądarce i przejrzyj kod podczas sortowania i stronicowania, aby zobaczyć dane pobrane 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ą ponownie przesyłane do elementu GridView.

Uwaga

Warstwa buforowania podana w pobieraniu towarzyszącym temu artykule nie jest kompletna. Zawiera tylko jedną klasę, ProductsCLktóra tylko uprawia kilka metod. Ponadto tylko jedna strona ASP.NET używa cl (~/Caching/FromTheArchitecture.aspx) wszystkich innych osób, które nadal odwołują się bezpośrednio do biblioteki BLL. Jeśli planujesz użycie cl w aplikacji, wszystkie wywołania z warstwy prezentacji powinny przejść do cl, co wymagałoby, aby klasy i metody CL obejmowały te klasy i metody w usłudze BLL obecnie używane przez warstwę prezentacji.

Podsumowanie

Buforowanie można stosować w warstwie prezentacji z kontrolkami SqlDataSource i ObjectDataSource w wersji 2.0 ASP.NET 2.0, natomiast w idealnym przypadku obowiązki buforowania będą 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 usłudze BLL i są wywoływane z warstwy prezentacji.

Przykłady warstwy buforowania, które omówiliśmy w tym artykule, a poprzednie samouczki wykazały reaktywne ładowanie. Podczas reaktywnego ładowania dane są ładowane do pamięci podręcznej tylko wtedy, gdy zostanie wykonane żądanie dotyczące danych i że brakuje danych z 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 do niego dotrzeć pod adresem mitchell@4GuysFromRolla.com. Lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.

Specjalne podziękowania

Ta seria samouczków została sprawdzona przez wielu pomocnych recenzentów. Główny recenzent tego samouczka to Teresa Murph. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.