Buforowanie danych przy uruchamianiu aplikacji (C#)
W dowolnej aplikacji internetowej niektóre dane będą często używane, a niektóre dane będą rzadko używane. Możemy poprawić wydajność naszej aplikacji ASP.NET, ładując z wyprzedzeniem często używane dane, technikę znaną jako buforowanie. W tym samouczku przedstawiono jedno podejście do proaktywnego ładowania, które polega na ładowaniu danych do pamięci podręcznej podczas uruchamiania aplikacji.
Wprowadzenie
W dwóch poprzednich samouczkach przedstawiono buforowanie danych w warstwach prezentacji i buforowania. W buforowaniu danych za pomocą obiektu ObjectDataSource przyjrzeliśmy się używaniu funkcji buforowania objectDataSource do buforowania danych w warstwie prezentacji. Buforowanie danych w architekturze zbadało buforowanie w nowej, oddzielnej warstwie buforowania. Oba te samouczki używały reaktywnego ładowania podczas pracy z pamięcią podręczną danych. W przypadku reaktywnego ładowania za każdym razem, gdy są wymagane dane, system najpierw sprawdza, czy znajduje się w pamięci podręcznej. Jeśli nie, pobiera dane ze źródła źródłowego, takiego jak baza danych, a następnie przechowuje je w pamięci podręcznej. Główną zaletą reaktywnego ładowania jest łatwość implementacji. Jedną z jego wad jest nierówna wydajność między żądaniami. Wyobraź sobie stronę, która używa warstwy buforowania z poprzedniego samouczka do wyświetlania informacji o produkcie. Gdy ta strona jest odwiedzana po raz pierwszy lub odwiedzana po raz pierwszy po eksmitowanym buforowanym danych z powodu ograniczeń pamięci lub osiągnięcia określonego wygaśnięcia, dane muszą zostać pobrane z bazy danych. W związku z tym żądania tych użytkowników będą trwać dłużej niż żądania użytkowników, które mogą być obsługiwane przez pamięć podręczną.
Proaktywne ładowanie zapewnia alternatywną strategię zarządzania pamięcią podręczną, która zapewnia wydajność między żądaniami, ładując buforowane dane przed ich potrzebami. Zazwyczaj proaktywne ładowanie używa pewnego procesu, który okresowo sprawdza lub jest powiadamiany o aktualizacji danych bazowych. Następnie ten proces aktualizuje pamięć podręczną, aby zachować jej świeżość. Aktywne ładowanie jest szczególnie przydatne, jeśli bazowe dane pochodzą z powolnego połączenia z bazą danych, usługi sieci Web lub innego szczególnie powolnego źródła danych. Jednak takie podejście do proaktywnego ładowania jest trudniejsze do zaimplementowania, ponieważ wymaga tworzenia, zarządzania i wdrażania procesu sprawdzania zmian i aktualizowania pamięci podręcznej.
Innym rozwiązaniem proaktywnego ładowania i typem, który będziemy eksplorować w tym samouczku, jest ładowanie danych do pamięci podręcznej podczas uruchamiania aplikacji. Takie podejście jest szczególnie przydatne w przypadku buforowania danych statycznych, takich jak rekordy w tabelach odnośników bazy danych.
Uwaga
Aby uzyskać bardziej szczegółowe informacje na temat różnic między proaktywnym i reaktywnym ładowaniem, a także listami zalet, wad i zaleceń dotyczących implementacji, zapoznaj się z sekcją Zarządzanie zawartością pamięci podręcznejprzewodnika po architekturze buforowania dla aplikacji .NET Framework.
Krok 1. Określanie danych do buforowania podczas uruchamiania aplikacji
Przykłady buforowania przy użyciu reaktywnego ładowania, które zbadano w poprzednich dwóch samouczkach, działają dobrze z danymi, które mogą okresowo ulec zmianie i nie są zbyt długie do wygenerowania. Ale jeśli buforowane dane nigdy się nie zmieniają, wygaśnięcie używane przez ładowanie reaktywne jest zbędne. Podobnie, jeśli buforowane dane trwają znacznie długo, to ci użytkownicy, których żądania znajdą pustą pamięć podręczną, będą musieli znieść długi czas oczekiwania podczas pobierania danych bazowych. Rozważ buforowanie danych statycznych i danych, które trwają wyjątkowo długo podczas uruchamiania aplikacji.
Chociaż bazy danych mają wiele dynamicznych, często zmieniających się wartości, większość ma również dość dużo danych statycznych. Na przykład praktycznie wszystkie modele danych mają co najmniej jedną kolumnę zawierającą określoną wartość z stałego zestawu wyborów. Tabela Patients
bazy danych może zawierać kolumnę PrimaryLanguage
, której zestaw wartości może być angielski, hiszpański, francuski, rosyjski, japoński itd. Często te typy kolumn są implementowane przy użyciu tabel odnośników. Zamiast przechowywać ciąg angielski lub francuski w Patients
tabeli, tworzona jest druga tabela zawierająca najczęściej dwie kolumny — unikatowy identyfikator i opis ciągu — z rekordem dla każdej możliwej wartości. Kolumna PrimaryLanguage
w Patients
tabeli przechowuje odpowiedni unikatowy identyfikator w tabeli odnośników. Na rysunku 1 pacjent John Doe jest językiem podstawowym języka angielskiego, podczas gdy Ed Johnson jest rosyjski.
Rysunek 1. Tabela Languages
jest tabelą odnośników używaną przez tabelę Patients
Interfejs użytkownika do edycji lub tworzenia nowego pacjenta zawiera listę rozwijaną dozwolonych języków wypełnionych rekordami w Languages
tabeli. Bez buforowania za każdym razem, gdy ten interfejs jest odwiedzany, system musi wykonywać zapytania względem Languages
tabeli. Jest to marne i niepotrzebne, ponieważ wartości tabeli odnośników zmieniają się bardzo rzadko, jeśli kiedykolwiek.
Dane można buforować Languages
przy użyciu tych samych technik reaktywnego ładowania zbadanego w poprzednich samouczkach. Ładowanie reaktywne używa jednak wygaśnięcia opartego na czasie, który nie jest potrzebny do statycznych danych tabeli odnośników. Podczas gdy buforowanie przy użyciu ładowania reaktywnego byłoby lepsze niż brak buforowania, najlepszym rozwiązaniem byłoby proaktywne ładowanie danych tabeli odnośników do pamięci podręcznej podczas uruchamiania aplikacji.
W tym samouczku przyjrzymy się sposobom buforowania danych tabeli odnośników i innych informacji statycznych.
Krok 2. Badanie różnych sposobów buforowania danych
Informacje mogą być programowo buforowane w aplikacji ASP.NET przy użyciu różnych metod. Widzieliśmy już, jak używać pamięci podręcznej danych w poprzednich samouczkach. Alternatywnie obiekty mogą być programowo buforowane przy użyciu statycznych elementów członkowskich lub stanu aplikacji.
Podczas pracy z klasą zazwyczaj należy najpierw utworzyć wystąpienie klasy, zanim będzie można uzyskać do nich dostęp. Aby na przykład wywołać metodę z jednej z klas w warstwie logiki biznesowej, należy najpierw utworzyć wystąpienie klasy:
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.SomeMethod();
productsAPI.SomeProperty = "Hello, World!";
Aby można było wywołać metodę SomeMethod lub pracować z elementem SomeProperty, należy najpierw utworzyć wystąpienie klasy przy użyciu słowa kluczowego new
. Niektóremethod i SomeProperty są skojarzone z określonym wystąpieniem. Okres istnienia tych elementów członkowskich jest związany z okresem istnienia skojarzonego obiektu. Z drugiej strony statyczne elementy członkowskie to zmienne, właściwości i metody, które są współużytkowane przez wszystkie wystąpienia klasy, a w związku z tym mają okres istnienia tak długo, jak klasa. Statyczne elementy członkowskie są oznaczone słowem kluczowym static
.
Oprócz statycznych elementów członkowskich dane mogą być buforowane przy użyciu stanu aplikacji. Każda aplikacja ASP.NET przechowuje kolekcję nazw/wartości współużytkowanych przez wszystkich użytkowników i strony aplikacji. Do tej kolekcji można uzyskać dostęp przy użyciu HttpContext
właściwości klasyApplication
i używanej z klasy ASP.NET strony kodowej w następujący sposób:
Application["key"] = value;
object value = Application["key"];
Pamięć podręczna danych udostępnia znacznie bogatszy interfejs API buforowania danych, zapewniając mechanizmy wygaśnięcia na podstawie czasu i zależności, priorytety elementów pamięci podręcznej itd. W przypadku statycznych elementów członkowskich i stanu aplikacji takie funkcje muszą zostać ręcznie dodane przez dewelopera strony. Jednak w przypadku buforowania danych podczas uruchamiania aplikacji przez cały okres istnienia aplikacji zalety pamięci podręcznej danych są częścią problemu. W tym samouczku przyjrzymy się kodowi, który używa wszystkich trzech technik buforowania danych statycznych.
Krok 3. BuforowanieSuppliers
danych tabeli
Tabele bazy danych Northwind, które zaimplementowaliśmy do tej pory, nie zawierają żadnych tradycyjnych tabel odnośników. Cztery tabele dataTable zaimplementowane w naszej usłudze DAL wszystkie tabele modelu, których wartości są niestatyczne. Zamiast spędzać czas, aby dodać nową tabelę DataTable do dal, a następnie nową klasę i metody do biblioteki BLL, w tym samouczku po prostu udawajmy, że Suppliers
dane tabeli są statyczne. W związku z tym możemy buforować te dane podczas uruchamiania aplikacji.
Aby rozpocząć, utwórz nową klasę o nazwie StaticCache.cs
w folderze CL
.
Rysunek 2. Tworzenie StaticCache.cs
klasy w folderze CL
Musimy dodać metodę, która ładuje dane podczas uruchamiania do odpowiedniego magazynu pamięci podręcznej, a także metody zwracające dane z tej pamięci podręcznej.
[System.ComponentModel.DataObject]
public class StaticCache
{
private static Northwind.SuppliersDataTable suppliers = null;
public static void LoadStaticCache()
{
// Get suppliers - cache using a static member variable
SuppliersBLL suppliersBLL = new SuppliersBLL();
suppliers = suppliersBLL.GetSuppliers();
}
[DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
public static Northwind.SuppliersDataTable GetSuppliers()
{
return suppliers;
}
}
Powyższy kod używa statycznej zmiennej składowej , suppliers
do przechowywania wyników z SuppliersBLL
metody klasy GetSuppliers()
, która jest wywoływana z LoadStaticCache()
metody . Metoda LoadStaticCache()
ma być wywoływana podczas uruchamiania aplikacji. Po załadowaniu tych danych podczas uruchamiania aplikacji każda strona, która musi współpracować z danymi dostawcy, może wywołać metodę StaticCache
klasy GetSuppliers()
. W związku z tym wywołanie bazy danych w celu uzyskania dostawców odbywa się tylko raz po uruchomieniu aplikacji.
Zamiast używać statycznej zmiennej składowej jako magazynu pamięci podręcznej, alternatywnie można użyć stanu aplikacji lub pamięci podręcznej danych. Poniższy kod przedstawia klasę ponownie w celu używania stanu aplikacji:
[System.ComponentModel.DataObject]
public class StaticCache
{
public static void LoadStaticCache()
{
// Get suppliers - cache using application state
SuppliersBLL suppliersBLL = new SuppliersBLL();
HttpContext.Current.Application["key"] = suppliersBLL.GetSuppliers();
}
[DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
public static Northwind.SuppliersDataTable GetSuppliers()
{
return HttpContext.Current.Application["key"] as Northwind.SuppliersDataTable;
}
}
W LoadStaticCache()
systemie informacje o dostawcy są przechowywane w kluczu zmiennej aplikacji. Jest zwracany jako odpowiedni typ (Northwind.SuppliersDataTable
) z GetSuppliers()
. Podczas gdy dostęp do stanu aplikacji można uzyskać w klasach kodu ASP.NET stron przy użyciu metody Application["key"]
, w architekturze musimy użyć HttpContext.Current.Application["key"]
polecenia , aby uzyskać bieżący HttpContext
element .
Podobnie pamięć podręczna danych może być używana jako magazyn pamięci podręcznej, jak pokazano w poniższym kodzie:
[System.ComponentModel.DataObject]
public class StaticCache
{
public static void LoadStaticCache()
{
// Get suppliers - cache using the data cache
SuppliersBLL suppliersBLL = new SuppliersBLL();
HttpRuntime.Cache.Insert(
/* key */ "key",
/* value */ suppliers,
/* dependencies */ null,
/* absoluteExpiration */ Cache.NoAbsoluteExpiration,
/* slidingExpiration */ Cache.NoSlidingExpiration,
/* priority */ CacheItemPriority.NotRemovable,
/* onRemoveCallback */ null);
}
[DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
public static Northwind.SuppliersDataTable GetSuppliers()
{
return HttpRuntime.Cache["key"] as Northwind.SuppliersDataTable;
}
}
Aby dodać element do pamięci podręcznej danych bez wygaśnięcia na podstawie czasu, użyj System.Web.Caching.Cache.NoAbsoluteExpiration
wartości i System.Web.Caching.Cache.NoSlidingExpiration
jako parametrów wejściowych. To konkretne przeciążenie metody pamięci podręcznej Insert
danych zostało wybrane, abyśmy mogli określić priorytet elementu pamięci podręcznej. Priorytet służy do określania, które elementy mają być scavenge z pamięci podręcznej, gdy dostępna pamięć jest niska. W tym miejscu użyjemy priorytetu NotRemovable
, co gwarantuje, że ten element pamięci podręcznej nie zostanie przeszycony.
Uwaga
Pobieranie tego samouczka implementuje klasę StaticCache
przy użyciu metody zmiennej składowej statycznej. Kod technik stanu aplikacji i pamięci podręcznej danych jest dostępny w komentarzach w pliku klasy.
Krok 4. Wykonywanie kodu podczas uruchamiania aplikacji
Aby wykonać kod po pierwszym uruchomieniu aplikacji internetowej, musimy utworzyć specjalny plik o nazwie Global.asax
. Ten plik może zawierać programy obsługi zdarzeń dla zdarzeń aplikacji, sesji i na poziomie żądania. W tym miejscu można dodać kod, który będzie wykonywany za każdym razem, gdy aplikacja się uruchamia.
Global.asax
Dodaj plik do katalogu głównego aplikacji internetowej, klikając prawym przyciskiem myszy nazwę projektu witryny internetowej w Eksplorator rozwiązań programu Visual Studio i wybierając pozycję Dodaj nowy element. W oknie dialogowym Dodawanie nowego elementu wybierz typ elementu Globalny klasa aplikacji, a następnie kliknij przycisk Dodaj.
Uwaga
Jeśli masz już Global.asax
plik w projekcie, typ elementu Globalnej klasy aplikacji nie będzie wyświetlany w oknie dialogowym Dodawanie nowego elementu.
Rysunek 3. Dodawanie Global.asax
pliku do katalogu głównego aplikacji internetowej (kliknij, aby wyświetlić obraz pełnowymiarowy)
Global.asax
Domyślny szablon pliku zawiera pięć metod w tagu po stronie <script>
serwera:
Application_Start
uruchamia się po pierwszym uruchomieniu aplikacji internetowejApplication_End
działa, gdy aplikacja jest zamykanaApplication_Error
jest wykonywany za każdym razem, gdy nieobsługiwany wyjątek osiągnie aplikacjęSession_Start
wykonuje po utworzeniu nowej sesjiSession_End
uruchamia się, gdy sesja wygasła lub porzucona
Program Application_Start
obsługi zdarzeń jest wywoływany tylko raz podczas cyklu życia aplikacji. Aplikacja uruchamia się po raz pierwszy zasób ASP.NET jest żądany z aplikacji i nadal działa do momentu ponownego uruchomienia aplikacji, co może się zdarzyć przez zmodyfikowanie zawartości /Bin
folderu, zmodyfikowanie , zmodyfikowanie Global.asax
zawartości w App_Code
folderze lub zmodyfikowanie Web.config
pliku, między innymi. Zapoznaj się z tematem ASP.NET Przegląd cyklu życia aplikacji , aby zapoznać się z bardziej szczegółowym omówieniem cyklu życia aplikacji.
W przypadku tych samouczków musimy tylko dodać kod do Application_Start
metody, więc możesz usunąć inne. W Application_Start
pliku po prostu wywołaj metodę StaticCache
klasy LoadStaticCache()
, która załaduje i buforuje informacje o dostawcy:
<%@ Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
StaticCache.LoadStaticCache();
}
</script>
To wszystko! Podczas uruchamiania LoadStaticCache()
aplikacji metoda pobierze informacje o dostawcy z biblioteki BLL i zapisze je w statycznej zmiennej składowej (lub dowolnego magazynu pamięci podręcznej, którego używasz w StaticCache
klasie). Aby zweryfikować to zachowanie, ustaw punkt przerwania w metodzie Application_Start
i uruchom aplikację. Należy pamiętać, że punkt przerwania jest trafiony po uruchomieniu aplikacji. Kolejne żądania nie powodują Application_Start
jednak wykonania metody.
Rysunek 4. Użyj punktu przerwania, aby sprawdzić, Application_Start
czy program obsługi zdarzeń jest wykonywany (kliknij, aby wyświetlić obraz pełnowymiarowy)
Uwaga
Jeśli nie trafisz do Application_Start
punktu przerwania podczas pierwszego rozpoczęcia debugowania, jest to spowodowane tym, że aplikacja została już uruchomiona. Wymuś ponowne uruchomienie aplikacji, modyfikując pliki Global.asax
lub Web.config
, a następnie spróbuj ponownie. Możesz po prostu dodać (lub usunąć) pusty wiersz na końcu jednego z tych plików, aby szybko ponownie uruchomić aplikację.
Krok 5. Wyświetlanie buforowanych danych
W tym momencie StaticCache
klasa ma wersję danych dostawcy buforowanych podczas uruchamiania aplikacji, do których można uzyskać dostęp za pośrednictwem metody GetSuppliers()
. Aby pracować z danymi z warstwy prezentacji, możemy użyć obiektu ObjectDataSource lub programowo wywołać StaticCache
metodę klasy GetSuppliers()
z klasy ASP.NET strony kodu za klasą. Przyjrzyjmy się używaniu kontrolek ObjectDataSource i GridView do wyświetlania buforowanych informacji o dostawcy.
Zacznij od otwarcia AtApplicationStartup.aspx
strony w folderze Caching
. Przeciągnij element GridView z przybornika do projektanta, ustawiając jego ID
właściwość na Suppliers
. Następnie z tagu inteligentnego GridView wybierz opcję utworzenia nowego obiektu ObjectDataSource o nazwie SuppliersCachedDataSource
. Skonfiguruj obiekt ObjectDataSource do użycia StaticCache
metody klasy GetSuppliers()
.
Rysunek 5. Konfigurowanie obiektu ObjectDataSource do używania StaticCache
klasy (kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 6. Używanie GetSuppliers()
metody do pobierania buforowanych danych dostawcy (kliknij, aby wyświetlić obraz pełnowymiarowy)
Po ukończeniu pracy kreatora program Visual Studio automatycznie doda pola BoundFields dla każdego pola danych w programie SuppliersDataTable
. Deklaratywne znaczniki GridView i ObjectDataSource powinny wyglądać podobnie do następujących:
<asp:GridView ID="Suppliers" runat="server" AutoGenerateColumns="False"
DataKeyNames="SupplierID" DataSourceID="SuppliersCachedDataSource"
EnableViewState="False">
<Columns>
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
InsertVisible="False" ReadOnly="True"
SortExpression="SupplierID" />
<asp:BoundField DataField="CompanyName" HeaderText="CompanyName"
SortExpression="CompanyName" />
<asp:BoundField DataField="Address" HeaderText="Address"
SortExpression="Address" />
<asp:BoundField DataField="City" HeaderText="City"
SortExpression="City" />
<asp:BoundField DataField="Country" HeaderText="Country"
SortExpression="Country" />
<asp:BoundField DataField="Phone" HeaderText="Phone"
SortExpression="Phone" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="SuppliersCachedDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="StaticCache" />
Rysunek 7 przedstawia stronę po wyświetleniu za pośrednictwem przeglądarki. Dane wyjściowe są takie same, jak w przypadku ściągania danych z klasy BLL SuppliersBLL
, ale użycie StaticCache
klasy zwraca dane dostawcy w pamięci podręcznej podczas uruchamiania aplikacji. Punkty przerwania można ustawić w metodzie StaticCache
klasy GetSuppliers()
, aby zweryfikować to zachowanie.
Rysunek 7. Dane buforowanego dostawcy są wyświetlane w widoku GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)
Podsumowanie
Większość każdego modelu danych zawiera sporo danych statycznych, zwykle implementowanych w formie tabel odnośników. Ponieważ te informacje są statyczne, nie ma powodu, aby stale uzyskiwać dostęp do bazy danych za każdym razem, gdy te informacje muszą być wyświetlane. Ponadto ze względu na jej statyczny charakter podczas buforowania danych nie ma potrzeby wygaśnięcia. W tym samouczku pokazano, jak pobrać takie dane i buforować je w pamięci podręcznej danych, stanie aplikacji i za pomocą zmiennej statycznej składowej. Te informacje są buforowane podczas uruchamiania aplikacji i pozostają w pamięci podręcznej przez cały okres istnienia aplikacji.
W tym samouczku i w ciągu ostatnich dwóch przyjrzeliśmy się buforowaniu danych na czas trwania okresu istnienia aplikacji, a także przy użyciu wygasań opartych na czasie. Jednak w przypadku buforowania danych bazy danych wygaśnięcie oparte na czasie może być mniejsze niż idealne. Zamiast okresowo opróżniać pamięć podręczną, najlepszym rozwiązaniem byłoby wykluczenie buforowanego elementu tylko wtedy, gdy bazowe dane bazy danych zostaną zmodyfikowane. Jest to idealne rozwiązanie, korzystając z zależności pamięci podręcznej SQL, które przeanalizujemy w następnym samouczku.
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. Recenzenci w tym samouczku byli Teresa Murphy i Zack Jones. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.