Używanie zależności pamięci podręcznej SQL (C#)

Autor : Scott Mitchell

Pobierz plik PDF

Najprostszą strategią buforowania jest umożliwienie wygaśnięcia buforowanych danych po upływie określonego czasu. Jednak takie proste podejście oznacza, że buforowane dane nie utrzymują skojarzenia z bazowym źródłem danych, co powoduje, że nieaktualne dane są przechowywane zbyt długo lub bieżące dane, które wygasły zbyt szybko. Lepszym rozwiązaniem jest użycie klasy SqlCacheDependency, tak aby dane były buforowane do momentu zmodyfikowania ich danych bazowych w bazie danych SQL. W tym samouczku pokazano, jak to zrobić.

Wprowadzenie

Techniki buforowania zbadane w danych buforowania za pomocą obiektu ObjectDataSource i danych buforowania w samouczkach Architektura używały wygaśnięcia opartego na czasie, aby wykluczyć dane z pamięci podręcznej po określonym przedziale czasu. Takie podejście to najprostszy sposób równoważenia wzrostu wydajności buforowania na nieaktualność danych. Wybierając czas wygaśnięcia x sekund, deweloper strony przyznaje, że korzyści z wydajności buforowania przez tylko x sekund, ale mogą być łatwe, że jej dane nigdy nie będą przestarzałe dłużej niż maksymalnie x sekund. Oczywiście w przypadku danych statycznych x można przedłużyć do okresu istnienia aplikacji internetowej, tak jak zostało to zbadane w samouczku Buforowanie danych podczas uruchamiania aplikacji .

Podczas buforowania danych bazy danych często wybierany jest termin wygaśnięcia, ale często jest nieodpowiednim rozwiązaniem. W idealnym przypadku dane bazy danych pozostaną w pamięci podręcznej do momentu zmodyfikowania bazowych danych w bazie danych; tylko wtedy pamięć podręczna zostanie eksmitowana. Takie podejście maksymalizuje zalety wydajności buforowania i minimalizuje czas trwania nieaktualnych danych. Jednak w celu korzystania z tych korzyści musi istnieć system, który wie, kiedy bazowe dane bazy danych zostały zmodyfikowane i eksmituje odpowiednie elementy z pamięci podręcznej. Przed ASP.NET 2.0 deweloperzy stron byli odpowiedzialni za implementację tego systemu.

ASP.NET 2.0 zapewnia klasęSqlCacheDependency i infrastrukturę niezbędną do określenia, kiedy w bazie danych wystąpiła zmiana, aby można było eksmitować odpowiednie buforowane elementy. Istnieją dwie techniki określania, kiedy dane bazowe uległy zmianie: powiadamianie i sondowanie. Po omówieniu różnic między powiadomieniami i sondowaniem utworzymy infrastrukturę niezbędną do obsługi sondowania, a następnie dowiesz się, jak używać SqlCacheDependency klasy w scenariuszach deklaratywnych i programowych.

Informacje o powiadomieniach i sondowaniu

Istnieją dwie techniki, których można użyć do określenia, kiedy dane w bazie danych zostały zmodyfikowane: powiadomienie i sondowanie. Dzięki powiadomieniu baza danych automatycznie powiadamia środowisko uruchomieniowe ASP.NET, gdy wyniki określonego zapytania zostały zmienione od czasu ostatniego wykonania zapytania, w którym to momencie są eksmitowane buforowane elementy skojarzone z zapytaniem. W przypadku sondowania serwer bazy danych przechowuje informacje o ostatniej aktualizacji określonych tabel. Środowisko uruchomieniowe ASP.NET okresowo sonduje bazę danych, aby sprawdzić, które tabele uległy zmianie od czasu ich wprowadzenia do pamięci podręcznej. Te tabele, których dane zostały zmodyfikowane, mają skojarzone elementy pamięci podręcznej wykluczone.

Opcja powiadomienia wymaga mniejszej konfiguracji niż sondowanie i jest bardziej szczegółowa, ponieważ śledzi zmiany na poziomie zapytania, a nie na poziomie tabeli. Niestety powiadomienia są dostępne tylko w pełnych wersjach programu Microsoft SQL Server 2005 (tj. wydaniach innych niż Express). Można jednak użyć opcji sondowania dla wszystkich wersji programu Microsoft SQL Server z wersji od 7.0 do 2005. Ponieważ te samouczki korzystają z wersji Express SQL Server 2005, skoncentrujemy się na konfigurowaniu i używaniu opcji sondowania. Zapoznaj się z sekcją Dalsze informacje na końcu tego samouczka, aby uzyskać więcej zasobów dotyczących możliwości powiadamiania SQL Server 2005 r.

W przypadku sondowania należy skonfigurować bazę danych tak, aby zawierała tabelę o nazwie AspNet_SqlCacheTablesForChangeNotification zawierającą trzy kolumny — tableName, notificationCreatedi changeId. Ta tabela zawiera wiersz dla każdej tabeli zawierającej dane, które mogą być potrzebne do użycia w zależności pamięci podręcznej SQL w aplikacji internetowej. Kolumna tableName określa nazwę tabeli, określając notificationCreated datę i godzinę dodania wiersza do tabeli. Kolumna changeId jest typu int i ma początkową wartość 0. Jej wartość jest zwiększana wraz z każdą modyfikacją tabeli.

Oprócz AspNet_SqlCacheTablesForChangeNotification tabeli baza danych musi również uwzględniać wyzwalacze dla każdej z tabel, które mogą pojawiać się w zależności pamięci podręcznej SQL. Te wyzwalacze są wykonywane za każdym razem, gdy wiersz jest wstawiany, aktualizowany lub usuwany i zwiększa wartość tabeli changeId w pliku AspNet_SqlCacheTablesForChangeNotification.

Środowisko uruchomieniowe ASP.NET śledzi bieżącą changeId wartość tabeli podczas buforowania danych przy użyciu SqlCacheDependency obiektu. Baza danych jest okresowo sprawdzana, a wszystkie SqlCacheDependency obiekty, których changeId wartość różni się od wartości w bazie danych, są eksmitowane, ponieważ inna changeId wartość wskazuje, że nastąpiła zmiana tabeli od czasu buforowania danych.

Krok 1. Eksplorowanieaspnet_regsql.exeprogramu wiersza polecenia

W przypadku podejścia sondowania baza danych musi być skonfigurowana tak, aby zawierała infrastrukturę opisaną powyżej: wstępnie zdefiniowaną tabelę (AspNet_SqlCacheTablesForChangeNotification), kilka procedur składowanych i wyzwalacze dla każdej z tabel, które mogą być używane w zależnościach pamięci podręcznej SQL w aplikacji internetowej. Te tabele, procedury składowane i wyzwalacze można tworzyć za pomocą programu aspnet_regsql.exewiersza polecenia , który znajduje się w folderze $WINDOWS$\Microsoft.NET\Framework\version . Aby utworzyć tabelę AspNet_SqlCacheTablesForChangeNotification i skojarzone procedury składowane, uruchom następujące polecenie w wierszu polecenia:

/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed

Uwaga

Aby wykonać te polecenia, określone dane logowania bazy danych muszą znajdować się w db_securityadmin rolach i db_ddladmin .

Aby na przykład dodać infrastrukturę do sondowania do bazy danych usługi Microsoft SQL Server o nazwie na serwerze bazy danych o nazwie pubsScottsServer przy użyciu uwierzytelniania systemu Windows, przejdź do odpowiedniego katalogu i w wierszu polecenia wprowadź:

aspnet_regsql.exe -S ScottsServer -E -d pubs -ed

Po dodaniu infrastruktury na poziomie bazy danych musimy dodać wyzwalacze do tych tabel, które będą używane w zależnościach pamięci podręcznej SQL. aspnet_regsql.exe Ponownie użyj programu wiersza polecenia, ale określ nazwę tabeli za pomocą przełącznika -t i zamiast używać -ed przełącznika , -etw następujący sposób:

/* For SQL Server authentication... */
aspnet_regsql.exe -S <i>server</i>
-U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
/* For Windows Authentication... */
aspnet_regsql.exe -S <i>server</i>
-E -d <i>database</i> -t <i>tableName</i> -et

Aby dodać wyzwalacze do authors tabel i titles w pubs bazie danych w usłudze ScottsServer, użyj polecenia :

aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et

Na potrzeby tego samouczka dodaj wyzwalacze do Productstabel , Categoriesi Suppliers . Przyjrzymy się konkretnej składni wiersza polecenia w kroku 3.

Krok 2. Odwoływanie się do bazy danych microsoft SQL Server 2005 Express Edition w programieApp_Data

Program aspnet_regsql.exe wiersza polecenia wymaga nazwy bazy danych i serwera w celu dodania niezbędnej infrastruktury sondowania. Ale jaka jest nazwa bazy danych i serwera bazy danych microsoft SQL Server 2005 Express, która znajduje się w folderzeApp_Data? Zamiast odnajdywać nazwy baz danych i serwerów, okazało się, że najprostszym podejściem jest dołączenie bazy danych do localhost\SQLExpress wystąpienia bazy danych i zmiana nazwy danych przy użyciu SQL Server Management Studio. Jeśli na komputerze jest zainstalowana jedna z pełnych wersji programu SQL Server 2005, prawdopodobnie na komputerze jest już zainstalowana SQL Server Management Studio. Jeśli masz tylko wersję Express, możesz pobrać bezpłatną wersję Microsoft SQL Server Management Studio Express Edition.

Zacznij od zamknięcia programu Visual Studio. Następnie otwórz SQL Server Management Studio i wybierz połączenie z serwerem localhost\SQLExpress przy użyciu uwierzytelniania systemu Windows.

Dołączanie do hosta lokalnego\SQLExpress Server

Rysunek 1. Dołączanie do localhost\SQLExpress serwera

Po nawiązaniu połączenia z serwerem program Management Studio wyświetli serwer i będzie miał podfoldery baz danych, zabezpieczeń i tak dalej. Kliknij prawym przyciskiem myszy folder Bazy danych i wybierz opcję Dołącz. Spowoduje to wyświetlenie okna dialogowego Dołączanie baz danych (zobacz Rysunek 2). Kliknij przycisk Dodaj i wybierz NORTHWND.MDF folder bazy danych w folderze aplikacji App_Data internetowej.

Dołącz element NORTHWND. Baza danych MDF z folderu App_Data

Rysunek 2. Dołączanie NORTHWND.MDF bazy danych z App_Data folderu (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Spowoduje to dodanie bazy danych do folderu Databases. Nazwa bazy danych może być pełną ścieżką do pliku bazy danych lub pełną ścieżką poprzedzaną identyfikatorem GUID. Aby uniknąć konieczności wpisywania długiej nazwy bazy danych podczas korzystania z narzędzia wiersza polecenia aspnet_regsql.exe, zmień nazwę bazy danych na bardziej przyjazną dla człowieka, klikając prawym przyciskiem myszy bazę danych po prostu dołączoną i wybierając polecenie Zmień nazwę. Zmieniono nazwę bazy danych na DataTutorials .

Zmienianie nazwy dołączonej bazy danych na bardziej Human-Friendly Nazwa

Rysunek 3. Zmiana nazwy dołączonej bazy danych na bardziej Human-Friendly nazwa

Krok 3. Dodawanie infrastruktury sondowania do bazy danych Northwind

Teraz, po dołączeniu NORTHWND.MDF bazy danych z App_Data folderu, możemy dodać infrastrukturę sondowania. Zakładając, że nazwa bazy danych została zmieniona na DataTutorials, uruchom następujące cztery polecenia:

aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -ed
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Products -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Categories -et
aspnet_regsql.exe -S localhost\SQLExpress -E -d DataTutorials -t Suppliers -et

Po uruchomieniu tych czterech poleceń kliknij prawym przyciskiem myszy nazwę bazy danych w programie Management Studio, przejdź do podmenu Zadania i wybierz polecenie Odłącz. Następnie zamknij program Management Studio i otwórz ponownie program Visual Studio.

Po ponownym otwarciu programu Visual Studio przejdź do szczegółów bazy danych za pomocą Eksploratora serwera. Zanotuj nową tabelę (AspNet_SqlCacheTablesForChangeNotification), nowe procedury składowane i wyzwalacze w Productstabelach , Categoriesi Suppliers .

Baza danych zawiera teraz niezbędną infrastrukturę sondowania

Rysunek 4. Baza danych zawiera teraz niezbędną infrastrukturę sondowania

Krok 4. Konfigurowanie usługi sondowania

Po utworzeniu wymaganych tabel, wyzwalaczy i procedur składowanych w bazie danych ostatnim krokiem jest skonfigurowanie usługi sondowania, która jest wykonywana przez Web.config określenie baz danych do użycia i częstotliwości sondowania w milisekundach. Poniższe znaczniki sonduje bazę danych Northwind co sekundę.

<?xml version="1.0"?>
<configuration>
   <connectionStrings>
      <add name="NORTHWNDConnectionString" connectionString=
          "Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\NORTHWND.MDF;
           Integrated Security=True;User Instance=True" 
           providerName="System.Data.SqlClient"/>
   </connectionStrings>
   <system.web>
      ...
      <!-- Configure the polling service used for SQL cache dependencies -->
      <caching>
         <sqlCacheDependency enabled="true" pollTime="1000" >
            <databases>
               <add name="NorthwindDB" 
                    connectionStringName="NORTHWNDConnectionString" />
            </databases>
         </sqlCacheDependency>
      </caching>
   </system.web>
</configuration>

Wartość name w elemecie <add> ( NorthwindDB ) kojarzy nazwę czytelną dla człowieka z określoną bazą danych. Podczas pracy z zależnościami pamięci podręcznej SQL musimy odwołać się do nazwy bazy danych zdefiniowanej tutaj, a także tabeli, na podstawie których są przechowywane dane w pamięci podręcznej. Zobaczymy, jak używać SqlCacheDependency klasy do programowego kojarzenia zależności pamięci podręcznej SQL z buforowanych danych w kroku 6.

Po ustanowieniu zależności pamięci podręcznej SQL system sondowania połączy się z bazami danych zdefiniowanymi w <databases> elementach co pollTime milisekundy i wykona procedurę AspNet_SqlCachePollingStoredProcedure składowaną. Ta procedura składowana — która została dodana z powrotem w kroku 3 przy użyciu aspnet_regsql.exe narzędzia wiersza polecenia — zwraca tableName wartości i changeId dla każdego rekordu w programie AspNet_SqlCacheTablesForChangeNotification. Nieaktualne zależności pamięci podręcznej SQL są eksmitowane z pamięci podręcznej.

Ustawienie pollTime wprowadza kompromis między wydajnością a nieaktualnością danych. pollTime Niewielka wartość zwiększa liczbę żądań do bazy danych, ale szybciej eksmituje nieaktualne dane z pamięci podręcznej. Większa pollTime wartość zmniejsza liczbę żądań bazy danych, ale zwiększa opóźnienie między zmianą danych zaplecza a wykluczeniem powiązanych elementów pamięci podręcznej. Na szczęście żądanie bazy danych wykonuje prostą procedurę składowaną, która zwraca tylko kilka wierszy z prostej, lekkiej tabeli. Jednak eksperymentuj z różnymi pollTime wartościami, aby znaleźć idealną równowagę między dostępem do bazy danych a nieaktualnością danych dla aplikacji. Najmniejsza pollTime dozwolona wartość to 500.

Uwaga

Powyższy przykład zawiera pojedynczą pollTime wartość w <sqlCacheDependency> elemecie, ale opcjonalnie można określić pollTime wartość w <add> elemecie. Jest to przydatne, jeśli określono wiele baz danych i chcesz dostosować częstotliwość sondowania na bazę danych.

Krok 5. Deklaratywna praca z zależnościami pamięci podręcznej SQL

W krokach od 1 do 4 przyjrzeliśmy się, jak skonfigurować niezbędną infrastrukturę bazy danych i skonfigurować system sondowania. Dzięki tej infrastrukturze możemy teraz dodawać elementy do pamięci podręcznej danych ze skojarzona zależność pamięci podręcznej SQL przy użyciu technik programowych lub deklaratywnych. W tym kroku sprawdzimy, jak deklaratywnie pracować z zależnościami pamięci podręcznej SQL. W kroku 6 przyjrzymy się programowej metodzie.

Samouczek Buforowanie danych za pomocą obiektu ObjectDataSource omówił funkcje deklaratywnego buforowania obiektu ObjectDataSource. Po prostu ustawiając EnableCaching właściwość na true i CacheDuration właściwość na jakiś interwał czasu, obiekt ObjectDataSource automatycznie buforuje dane zwrócone z jego obiektu bazowego dla określonego interwału. Obiekt ObjectDataSource może również używać co najmniej jednej zależności pamięci podręcznej SQL.

Aby zademonstrować użycie zależności pamięci podręcznej SQL deklaratywnie, otwórz SqlCacheDependencies.aspx stronę w Caching folderze i przeciągnij element GridView z przybornika do Projektant. Ustaw element GridView na IDProductsDeclarative i z jego tagu inteligentnego wybierz powiązanie go z nowym obiektem ObjectDataSource o nazwie ProductsDataSourceDeclarative.

Tworzenie nowego obiektuDataSource o nazwie ProductsDataSourceDeclarative

Rysunek 5. Tworzenie nowego obiektu ObjectDataSource Nazwane ProductsDataSourceDeclarative (kliknij, aby wyświetlić obraz pełnowymiarowy)

Skonfiguruj obiekt ObjectDataSource do użycia ProductsBLL klasy i ustaw listę rozwijaną na karcie SELECT na GetProducts()wartość . Na karcie UPDATE wybierz przeciążenie z trzema UpdateProduct parametrami wejściowymi — productName, unitPricei productID. Ustaw listy rozwijane na wartość (Brak) na kartach INSERT i DELETE.

Używanie przeciążenia UpdateProduct z trzema parametrami wejściowymi

Rysunek 6. Użycie przeciążenia UpdateProduct z trzema parametrami wejściowymi (kliknij, aby wyświetlić obraz pełnowymiarowy)

Ustaw listę Drop-Down na (Brak) dla kart INSERT i DELETE

Rysunek 7. Ustawianie listy Drop-Down na (Brak) dla kart INSERT i DELETE (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy Kreatora konfigurowania źródła danych program Visual Studio utworzy pola BoundFields i CheckBoxFields w elemecie GridView dla każdego pola danych. Usuń wszystkie pola, ale ProductName, CategoryNamei UnitPricei sformatuj te pola zgodnie z potrzebami. W tagu inteligentnym GridView zaznacz pola wyboru Włącz stronicowanie, Włącz sortowanie i Włącz edytowanie. Program Visual Studio ustawi właściwość ObjectDataSource na OldValuesParameterFormatStringoriginal_{0}. Aby funkcja edycji elementu GridView działała prawidłowo, usuń tę właściwość całkowicie ze składni deklaratywnej lub ustaw ją z powrotem na wartość domyślną . {0}

Na koniec dodaj kontrolkę Etykieta sieci Web nad kontrolką GridView i ustaw jej ID właściwość na ODSEvents i jej EnableViewState właściwość na false. Po wprowadzeniu tych zmian znacznik deklaratywny strony powinien wyglądać podobnie do poniższego. Należy pamiętać, że wprowadzono wiele dostosowań estetycznych w polach GridView, które nie są niezbędne do zademonstrowania funkcji zależności pamięci podręcznej SQL.

<asp:Label ID="ODSEvents" runat="server" EnableViewState="False" />
<asp:GridView ID="ProductsDeclarative" runat="server" 
    AutoGenerateColumns="False" DataKeyNames="ProductID" 
    DataSourceID="ProductsDataSourceDeclarative" 
    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") %>' />
            </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"
                    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" Display="Dynamic" 
                    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="ProductsDataSourceDeclarative" runat="server" 
    SelectMethod="GetProducts" TypeName="ProductsBLL" 
    UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

Następnie utwórz procedurę obsługi zdarzeń dla zdarzenia ObjectDataSource Selecting i dodaj w nim następujący kod:

protected void ProductsDataSourceDeclarative_Selecting
    (object sender, ObjectDataSourceSelectingEventArgs e)
{
    ODSEvents.Text = "-- Selecting event fired";
}

Pamiętaj, że zdarzenie ObjectDataSource Selecting jest uruchamiane tylko w przypadku pobierania danych z jego obiektu bazowego. Jeśli obiekt ObjectDataSource uzyskuje dostęp do danych z własnej pamięci podręcznej, to zdarzenie nie zostanie wyzwolone.

Teraz odwiedź tę stronę za pośrednictwem przeglądarki. Ponieważ jeszcze zaimplementowaliśmy jakiekolwiek buforowanie, za każdym razem, gdy strona, sortowanie lub edytowanie siatki strona powinna wyświetlić tekst "Wybranie zdarzenia wyzwolonego, jak pokazano na rysunku 8.

Funkcja ObjectDataSource wybierająca zdarzenie jest uruchamiana za każdym razem, gdy element GridView jest stronicowany, edytowany lub posortowany

Rysunek 8. Zdarzenie ObjectDataSource Selecting jest wyzwalane za każdym razem, gdy element GridView jest stronicowany, edytowany lub posortowany (kliknij, aby wyświetlić obraz pełnowymiarowy)

Jak pokazano w samouczku Buforowanie danych za pomocą obiektu ObjectDataSource , ustawienie EnableCaching właściwości powoduje true , że właściwość ObjectDataSource będzie buforować swoje dane przez czas określony przez jego CacheDuration właściwość. Obiekt ObjectDataSource ma SqlCacheDependency również właściwość, która dodaje co najmniej jedną zależność pamięci podręcznej SQL do buforowanych danych przy użyciu wzorca:

databaseName1:tableName1;databaseName2:tableName2;...

Gdzie databaseName to nazwa bazy danych określona w name atrybucie <add> elementu w , Web.configa tableName jest nazwą tabeli bazy danych. Aby na przykład utworzyć obiekt ObjectDataSource, który buforuje dane na czas nieokreślony na podstawie zależności pamięci podręcznej SQL od tabeli Northwind s Products , ustaw właściwość ObjectDataSource EnableCaching na true i jej SqlCacheDependency właściwość na NorthwindDB:Products .

Uwaga

Można użyć zależności pamięci podręcznej SQL i wygaśnięcia opartego na czasie, ustawiając wartość EnableCachingtruena , CacheDuration na interwał czasu oraz SqlCacheDependency na nazwy baz danych i tabeli. Obiekt ObjectDataSource wykluczy swoje dane po osiągnięciu wygaśnięcia opartego na czasie lub gdy system sondowania zauważa, że bazowe dane bazy danych uległy zmianie, w zależności od tego, co nastąpi wcześniej.

Element GridView w programie SqlCacheDependencies.aspx wyświetla dane z dwóch tabel — Products i Categories (pole produktu CategoryName jest pobierane za pośrednictwem elementu JOIN .Categories W związku z tym chcemy określić dwie zależności pamięci podręcznej SQL: NorthwindDB:Products; NorthwindDB:Categories .

Konfigurowanie obiektu ObjectDataSource do obsługi buforowania przy użyciu zależności pamięci podręcznej SQL w produktach i kategoriach

Rysunek 9. Konfigurowanie obiektu ObjectDataSource do obsługi buforowania przy użyciu zależności Products pamięci podręcznej SQL i Categories (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po skonfigurowaniu obiektu ObjectDataSource do obsługi buforowania ponownie przejdź do strony za pośrednictwem przeglądarki. Ponownie tekst "Wyzwolone zdarzenie wybierania powinno pojawić się podczas pierwszej wizyty na stronie, ale powinien odejść podczas stronicowania, sortowania lub klikania przycisków Edytuj lub Anuluj. Dzieje się tak dlatego, że po załadowaniu danych do pamięci podręcznej ObjectDataSource pozostają tam do momentu Products modyfikacji tabel lub Categories lub zaktualizowania danych za pośrednictwem kontrolki GridView.

Po stronicowaniu przez siatkę i zaniesieniu braku tekstu "Wybieranie zdarzenia wyzwolonego tekstu otwórz nowe okno przeglądarki i przejdź do samouczka Podstawy w sekcji Edytowanie, Wstawianie i Usuwanie (~/EditInsertDelete/Basics.aspx). Zaktualizuj nazwę lub cenę produktu. Następnie w oknie pierwszej przeglądarki wyświetl inną stronę danych, posortuj siatkę lub kliknij przycisk Edytuj wiersz. Tym razem zdarzenie wyboru powinno zostać ponownie wyzwolone, ponieważ bazowe dane bazy danych zostały zmodyfikowane (patrz Rysunek 10). Jeśli tekst nie jest wyświetlany, poczekaj chwilę i spróbuj ponownie. Pamiętaj, że usługa sondowania sprawdza zmiany Products w tabeli co pollTime milisekundy, dlatego występuje opóźnienie między aktualizowaniem danych bazowych a eksmitowaniem buforowanych danych.

Modyfikowanie tabeli products eksmituje buforowane dane produktu

Rysunek 10. Modyfikowanie tabeli products eksmituje buforowane dane produktu (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 6. Programowe praca z klasąSqlCacheDependency

W samouczku Buforowanie danych w architekturze przedstawiono korzyści wynikające z używania oddzielnej warstwy buforowania w architekturze, a nie ściśle sprzężenia buforowania z obiektem ObjectDataSource. W tym samouczku utworzyliśmy klasę ProductsCL , która programowo współpracuje z pamięcią podręczną danych. Aby korzystać z zależności pamięci podręcznej SQL w warstwie buforowania, użyj SqlCacheDependency klasy .

W systemie SqlCacheDependency sondowania obiekt musi być skojarzony z określoną bazą danych i parą tabel. Na przykład poniższy kod tworzy SqlCacheDependency obiekt na podstawie tabeli bazy danych Products Northwind:

Caching.SqlCacheDependency productsTableDependency = 
    new Caching.SqlCacheDependency("NorthwindDB", "Products");

Dwa parametry SqlCacheDependency wejściowe konstruktora to odpowiednio nazwy baz danych i tabel. Podobnie jak we właściwości ObjectDataSource SqlCacheDependency , używana nazwa bazy danych jest taka sama jak wartość określona w name atrybucie <add> elementu w Web.config. Nazwa tabeli to rzeczywista nazwa tabeli bazy danych.

Aby skojarzyć SqlCacheDependency element z elementem dodanym do pamięci podręcznej danych, użyj jednego z Insert przeciążeń metody akceptujących zależność. Poniższy kod dodaje wartość do pamięci podręcznej danych przez nieokreślony czas trwania, ale kojarzy go z tabelą SqlCacheDependencyProducts . Krótko mówiąc, wartość pozostanie w pamięci podręcznej, dopóki nie zostanie eksmitowana z powodu ograniczeń pamięci lub ponieważ system sondowania wykrył, że Products tabela uległa zmianie od czasu jego buforowania.

Caching.SqlCacheDependency productsTableDependency = 
    new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key, 
             value, 
             productsTableDependency, 
             System.Web.Caching.Cache.NoAbsoluteExpiration, 
             System.Web.Caching.Cache.NoSlidingExpiration);

Klasa warstwy ProductsCL buforowania buforuje obecnie dane z Products tabeli przy użyciu wygaśnięcia na podstawie czasu 60 sekund. Zaktualizujmy tę klasę, aby zamiast tego korzystała z zależności pamięci podręcznej SQL. Metoda ProductsCL klasy s AddCacheItem , która jest odpowiedzialna za dodawanie danych do pamięci podręcznej, obecnie zawiera następujący kod:

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

Zaktualizuj ten kod, aby użyć SqlCacheDependency obiektu zamiast zależności pamięci podręcznej MasterCacheKeyArray :

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Add the SqlCacheDependency objects for Products
    Caching.SqlCacheDependency productsTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Products");
    // Add the item to the data cache using productsTableDependency
    DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency, 
        Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}

Aby przetestować tę funkcję, dodaj element GridView do strony poniżej istniejącej ProductsDeclarative kontrolki GridView. Ustaw ten nowy element GridView na IDProductsProgrammatic i, za pomocą tagu inteligentnego, powiąż go z nowym obiektem ObjectDataSource o nazwie ProductsDataSourceProgrammatic. Skonfiguruj obiekt ObjectDataSource do użycia ProductsCL klasy, ustawiając listy rozwijane na kartach SELECT i UPDATE odpowiednio na GetProducts i UpdateProduct.

Konfigurowanie obiektu ObjectDataSource do używania klasy ProductsCL

Rysunek 11. Konfigurowanie obiektu ObjectDataSource do używania ProductsCL klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)

Wybierz metodę GetProducts z listy Drop-Down SELECT Tab

Rysunek 12. Wybierz metodę GetProducts z listy Drop-Down SELECT Tab (Kliknij, aby wyświetlić obraz pełnowymiarowy)

Wybierz metodę UpdateProduct z listy Drop-Down kart UPDATE

Rysunek 13. Wybierz metodę UpdateProduct z listy Drop-Down kart AKTUALIZACJI (kliknij, aby wyświetlić obraz pełnowymiarowy)

Po ukończeniu pracy Kreatora konfigurowania źródła danych program Visual Studio utworzy pola BoundFields i CheckBoxFields w elemecie GridView dla każdego pola danych. Podobnie jak w przypadku pierwszego elementu GridView dodanego do tej strony, usuń wszystkie pola, ale ProductName, CategoryNamei UnitPricesformatuj te pola zgodnie z potrzebami. W tagu inteligentnym GridView zaznacz pola wyboru Włącz stronicowanie, Włącz sortowanie i Włącz edytowanie. Podobnie jak w przypadku ProductsDataSourceDeclarative obiektu ObjectDataSource, program Visual Studio ustawi ProductsDataSourceProgrammatic właściwość ObjectDataSource OldValuesParameterFormatString na original_{0}. Aby funkcja edycji elementu GridView działała prawidłowo, ustaw tę właściwość z powrotem na {0} (lub całkowicie usuń przypisanie właściwości ze składni deklaratywnej).

Po wykonaniu tych zadań wynikowe znaczniki deklaratywne GridView i ObjectDataSource powinny wyglądać następująco:

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

Aby przetestować zależność pamięci podręcznej SQL w warstwie buforowania, ustaw punkt przerwania w ProductCL metodzie klasy s AddCacheItem , a następnie rozpocznij debugowanie. Podczas pierwszej wizyty SqlCacheDependencies.aspxpunkt przerwania powinien zostać trafiony, ponieważ dane są żądane po raz pierwszy i umieszczone w pamięci podręcznej. Następnie przejdź do innej strony w elemecie GridView lub posortuj jedną z kolumn. Powoduje to ponowne zapytanie danych elementu GridView, ale dane powinny znajdować się w pamięci podręcznej, ponieważ Products tabela bazy danych nie została zmodyfikowana. Jeśli dane nie znajdują się wielokrotnie w pamięci podręcznej, upewnij się, że na komputerze jest wystarczająca ilość pamięci i spróbuj ponownie.

Po stronicowaniu za pomocą kilku stron kontrolki GridView otwórz drugie okno przeglądarki i przejdź do samouczka Podstawy w sekcji Edytowanie, Wstawianie i Usuwanie (~/EditInsertDelete/Basics.aspx). Zaktualizuj rekord z tabeli Products, a następnie w pierwszym oknie przeglądarki wyświetl nową stronę lub kliknij jeden z nagłówków sortowania.

W tym scenariuszu zobaczysz jedną z dwóch rzeczy: zostanie trafiony punkt przerwania wskazujący, że buforowane dane zostały eksmitowane z powodu zmiany w bazie danych; lub punkt przerwania nie zostanie trafiony, co oznacza, że SqlCacheDependencies.aspx teraz pokazuje nieaktualne dane. Jeśli punkt przerwania nie zostanie trafiony, prawdopodobnie usługa sondowania nie została jeszcze wyzwolona od czasu zmiany danych. Pamiętaj, że usługa sondowania sprawdza zmiany Products w tabeli co pollTime milisekundy, dlatego występuje opóźnienie między aktualizowaniem danych bazowych a eksmitowaniem buforowanych danych.

Uwaga

To opóźnienie jest bardziej prawdopodobne podczas edytowania jednego z produktów za pośrednictwem kontrolki GridView w programie SqlCacheDependencies.aspx. W samouczku Buforowanie danych w architekturze dodaliśmy MasterCacheKeyArray zależność pamięci podręcznej, aby upewnić się, że dane edytowane za pomocą ProductsCL metody klasy UpdateProduct zostały wykluczone z pamięci podręcznej. Jednak ta zależność pamięci podręcznej została zastąpiona podczas modyfikowania AddCacheItem metody wcześniej w tym kroku, a w związku z tym ProductsCL klasa będzie nadal pokazywać buforowane dane, dopóki system sondowania nie zanotuje zmiany Products w tabeli. Zobaczymy, jak przywrócić zależność pamięci podręcznej MasterCacheKeyArray w kroku 7.

Krok 7. Kojarzenie wielu zależności z elementem buforowanym

Należy pamiętać, że MasterCacheKeyArray zależność pamięci podręcznej służy do zapewnienia, że wszystkie dane związane z produktem są eksmitowane z pamięci podręcznej po zaktualizowaniu dowolnego elementu skojarzonego z nim. Na przykład GetProductsByCategoryID(categoryID) metoda buforuje ProductsDataTables wystąpienia dla każdej unikatowej wartości categoryID . Jeśli jeden z tych obiektów zostanie eksmitowany, MasterCacheKeyArray zależność pamięci podręcznej gwarantuje również usunięcie pozostałych obiektów. Bez tej zależności pamięci podręcznej, gdy buforowane dane są modyfikowane, istnieje możliwość, że inne buforowane dane produktu mogą być nieaktualne. W związku z tym ważne jest, aby zachować zależność pamięci podręcznej MasterCacheKeyArray podczas korzystania z zależności pamięci podręcznej SQL. Jednak metoda pamięci podręcznej Insert danych zezwala tylko na pojedynczy obiekt zależności.

Ponadto podczas pracy z zależnościami pamięci podręcznej SQL może być konieczne skojarzenie wielu tabel bazy danych jako zależności. Na przykład ProductsDataTable buforowany w ProductsCL klasie zawiera nazwy kategorii i dostawców dla każdego produktu, ale AddCacheItem metoda używa tylko zależności od Products. W takiej sytuacji, jeśli użytkownik aktualizuje nazwę kategorii lub dostawcy, buforowane dane produktu pozostaną w pamięci podręcznej i będą nieaktualne. W związku z tym chcemy, aby buforowane dane produktu zależały nie tylko Products od tabeli, ale także tabel Categories i Suppliers .

KlasaAggregateCacheDependency zapewnia metodę kojarzenia wielu zależności z elementem pamięci podręcznej. Zacznij od utworzenia AggregateCacheDependency wystąpienia. Następnie dodaj zestaw zależności przy użyciu AggregateCacheDependency metody s Add . Podczas wstawiania elementu do pamięci podręcznej danych następnie przekaż AggregateCacheDependency wystąpienie. Gdy dowolna z AggregateCacheDependency zależności wystąpienia ulegnie zmianie, buforowany element zostanie wykluczony.

Poniżej przedstawiono zaktualizowany kod ProductsCL dla metody klasy s AddCacheItem . Metoda tworzy zależność pamięci podręcznej MasterCacheKeyArray wraz z obiektami SqlCacheDependency dla Productstabel , Categoriesi Suppliers . Wszystkie te elementy są łączone w jeden AggregateCacheDependency obiekt o nazwie aggregateDependencies, który następnie jest przekazywany do Insert metody .

private void AddCacheItem(string rawKey, object value)
{
    System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
    // Make sure MasterCacheKeyArray[0] is in the cache and create a depedency
    DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
    Caching.CacheDependency masterCacheKeyDependency = 
        new Caching.CacheDependency(null, MasterCacheKeyArray);
    // Add the SqlCacheDependency objects for Products, Categories, and Suppliers
    Caching.SqlCacheDependency productsTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Products");
    Caching.SqlCacheDependency categoriesTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Categories");
    Caching.SqlCacheDependency suppliersTableDependency = 
        new Caching.SqlCacheDependency("NorthwindDB", "Suppliers");
    // Create an AggregateCacheDependency
    Caching.AggregateCacheDependency aggregateDependencies = 
        new Caching.AggregateCacheDependency();
    aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency, 
        categoriesTableDependency, suppliersTableDependency);
    DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies, 
        Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}

Przetestuj ten nowy kod. Teraz zmiany w Productstabelach , Categorieslub Suppliers powodują eksmitowanie buforowanych danych. ProductsCL Ponadto metoda klasy sUpdateProduct, która jest wywoływana podczas edytowania produktu za pośrednictwem elementu GridView, eksmituje MasterCacheKeyArray zależność pamięci podręcznej, co powoduje eksmitowanie buforowanej ProductsDataTable pamięci podręcznej i ponowne pobieranie danych w następnym żądaniu.

Uwaga

Zależności pamięci podręcznej SQL mogą być również używane z buforowaniem danych wyjściowych. Aby zapoznać się z pokazem tej funkcji, zobacz: Używanie buforowania wyjściowego ASP.NET z SQL Server.

Podsumowanie

Podczas buforowania danych bazy danych dane pozostaną w pamięci podręcznej, dopóki nie zostaną zmodyfikowane w bazie danych. W przypadku ASP.NET 2.0 zależności pamięci podręcznej SQL można tworzyć i używać w scenariuszach deklaratywnych i programowych. Jednym z wyzwań związanych z tym podejściem jest odkrycie, kiedy dane zostały zmodyfikowane. Pełne wersje usługi Microsoft SQL Server 2005 zapewniają możliwości powiadomień, które mogą powiadamiać aplikację o zmianie wyniku zapytania. W przypadku wersji Express Edition SQL Server 2005 i starszych wersji SQL Server należy użyć systemu sondowania. Na szczęście skonfigurowanie niezbędnej infrastruktury sondowania jest dość proste.

Szczęśliwe programowanie!

Dalsze informacje

Aby uzyskać więcej informacji na temat tematów omówionych w tym samouczku, zapoznaj się z następującymi zasobami:

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. Recenzenci w tym samouczku to Marko Rangel, Teresa Murphy i Hilton Giesenow. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.