Delen via


Gegevens opslaan in cache bij opstarten van toepassingen (VB)

door Scott Mitchell

PDF downloaden

In een webtoepassing worden sommige gegevens vaak gebruikt en worden sommige gegevens niet vaak gebruikt. We kunnen de prestaties van onze ASP.NET toepassing verbeteren door vooraf de veelgebruikte gegevens te laden, een techniek die bekend staat als caching. In deze zelfstudie ziet u een benadering voor proactief laden, namelijk het laden van gegevens in de cache bij het opstarten van de toepassing.

Introductie

In de twee vorige tutorials is gekeken naar het cachen van gegevens in de presentatie- en cachelagen. In cachegegevens met de ObjectDataSource hebben we gekeken naar het gebruik van de cachefuncties van ObjectDataSource om gegevens in de presentatielaag op te cachen. Cachegegevens in de architectuur onderzochten caching in een nieuwe, afzonderlijke cachelaag. In beide tutorials werd reactief laden gebruikt voor het werken met de gegevenscache. Bij reactief laden, telkens wanneer de gegevens worden aangevraagd, controleert het systeem eerst of deze zich in de cache bevindt. Als dat niet het probleem is, worden de gegevens opgehaald uit de oorspronkelijke bron, zoals de database, en vervolgens opgeslagen in de cache. Het belangrijkste voordeel van reactief laden is het gemak van de implementatie. Een van de nadelen is de ongelijke prestatie over verschillende verzoeken. Stel u een pagina voor die gebruikmaakt van de cachelaag uit de vorige zelfstudie om productgegevens weer te geven. Wanneer deze pagina voor het eerst wordt bezocht of voor het eerst wordt bezocht nadat de gegevens in de cache zijn verwijderd vanwege geheugenbeperkingen of de opgegeven vervaldatum zijn bereikt, moeten de gegevens worden opgehaald uit de database. Deze aanvragen van gebruikers duren daarom langer dan gebruikersaanvragen die door de cache kunnen worden verwerkt.

Proactief laden biedt een alternatieve strategie voor cachebeheer waarmee de prestaties van aanvragen worden vereffend door de gegevens in de cache te laden voordat deze nodig zijn. Proactief laden maakt doorgaans gebruik van een bepaald proces dat periodiek wordt gecontroleerd of op de hoogte wordt gesteld wanneer er een update van de onderliggende gegevens is uitgevoerd. Met dit proces wordt vervolgens de cache bijgewerkt om deze nieuw te houden. Proactief laden is vooral handig als de onderliggende gegevens afkomstig zijn van een trage databaseverbinding, een webservice of een andere bijzonder trage gegevensbron. Maar deze benadering voor proactief laden is moeilijker te implementeren, omdat er een proces moet worden gemaakt, beheerd en geïmplementeerd om te controleren op wijzigingen en de cache bij te werken.

Een andere variant van proactief laden, en het type dat we in deze zelfstudie gaan verkennen, is het laden van gegevens in de cache tijdens het opstarten van de applicatie. Deze methode is vooral handig voor het opslaan van statische gegevens, zoals de records in opzoektabellen in de database.

Opmerking

Raadpleeg de sectie Inhoud van een cache van de cachearchitectuurhandleiding voor .NET Framework-toepassingen voor een uitgebreidere kijk op de verschillen tussen proactief en reactief laden, evenals lijsten met voor- en nadelen en implementatieaanbeveling.

Stap 1: Bepalen welke gegevens moeten worden opgeslagen bij het opstarten van de toepassing

De cachevoorbeelden die gebruikmaken van reactief laden die we in de vorige twee zelfstudies hebben onderzocht, werken goed met gegevens die periodiek kunnen worden gewijzigd en die niet exorbitant lang duren om te genereren. Maar als de gegevens in de cache nooit veranderen, is de vervaldatum die door reactief laden wordt gebruikt overbodig. Wanneer de gegevens die in de cache worden opgeslagen uitzonderlijk lang duren om te genereren, moeten de gebruikers wiens aanvragen een lege cache tegenkomen langer wachten terwijl de onderliggende gegevens worden opgehaald. Overweeg om statische gegevens en gegevens in de cache op te nemen die uitzonderlijk lang duren voordat ze worden gegenereerd bij het opstarten van de toepassing.

Hoewel databases veel dynamische, vaak veranderende waarden hebben, hebben de meeste ook een redelijke hoeveelheid statische gegevens. Vrijwel alle gegevensmodellen hebben bijvoorbeeld een of meer kolommen die een bepaalde waarde uit een vaste set keuzen bevatten. Een Patients databasetabel kan een PrimaryLanguage kolom hebben waarvan de set waarden Engels, Spaans, Frans, Russisch, Japans, enzovoort kan zijn. Vaak worden deze typen kolommen geïmplementeerd met behulp van opzoektabellen. In plaats van de tekenreeks Engels of Frans in de Patients tabel op te slaan, wordt er een tweede tabel gemaakt met meestal twee kolommen: een unieke identificator en een tekenreeksbeschrijving, met een record voor elke mogelijke waarde. In PrimaryLanguage de kolom in de Patients tabel wordt de bijbehorende unieke id opgeslagen in de opzoektabel. In afbeelding 1 is patiënt John Doe's primaire taal Engels, terwijl Ed Johnson s Russisch is.

De tabel Talen is een opzoektabel die wordt gebruikt door de patiëntentabel

Afbeelding 1: De Languages tabel is een opzoektabel die wordt gebruikt door de Patients tabel

De gebruikersinterface voor het bewerken of maken van een nieuwe patiënt bevat een vervolgkeuzelijst met toegestane talen die door de records in de Languages tabel zijn ingevuld. Als deze interface niet in de cache wordt opgeslagen, moet het systeem elke keer een query uitvoeren op de Languages tabel. Dit is verspilling en onnodig, omdat opzoektabelwaarden zeer zelden veranderen, indien ooit.

We kunnen de Languages gegevens opslaan met behulp van dezelfde reactieve laadtechnieken die in de vorige zelfstudies zijn onderzocht. Reactief laden maakt echter gebruik van een verlooptijd op basis van tijd, wat niet nodig is voor statische opzoektabelgegevens. Hoewel caching met reactief laden beter is dan helemaal geen caching, is de beste benadering om proactief de opzoektabelgegevens in de cache te laden bij het opstarten van de toepassing.

In deze zelfstudie bekijken we hoe we opzoektabelgegevens en andere statische informatie in de cache opslaan.

Stap 2: de verschillende manieren om gegevens in de cache te bekijken

Informatie kan programmatisch worden opgeslagen in een ASP.NET toepassing met behulp van verschillende benaderingen. We hebben al gezien hoe we de gegevenscache in eerdere zelfstudies kunnen gebruiken. U kunt objecten ook programmatisch opslaan in de cache door middel van statische leden of applicatiestatus.

Wanneer u met een klasse werkt, moet de klasse doorgaans eerst worden geïnstantieerd voordat er toegang kan worden verkregen tot de leden ervan. Als u bijvoorbeeld een methode wilt aanroepen vanuit een van de klassen in onze bedrijfslogicalaag, moet u eerst een exemplaar van de klasse maken:

Dim productsAPI As New ProductsBLL()
productsAPI.SomeMethod()
productsAPI.SomeProperty = "Hello, World!"

Voordat we SomeMethod kunnen aanroepen of met SomeProperty kunnen werken, moeten we eerst een exemplaar van de klasse maken met behulp van het New trefwoord. SomeMethod en SomeProperty zijn gekoppeld aan een bepaald exemplaar. De levensduur van deze leden is gekoppeld aan de levensduur van hun gekoppelde object. Statische leden zijn daarentegen variabelen, eigenschappen en methoden die worden gedeeld tussen alle exemplaren van de klasse en dus een levensduur hebben zolang de klasse. Statische leden worden aangeduid met het trefwoord Shared.

Naast statische leden kunnen gegevens in de cache worden opgeslagen met behulp van de toepassingsstatus. Elke ASP.NET toepassing onderhoudt een verzameling naam/waarde die wordt gedeeld door alle gebruikers en pagina's van de toepassing. Deze verzameling kan worden geopend met behulp van de HttpContext klasse-eigenschapApplicationen worden gebruikt vanuit de code-behind klasse van een ASP.NET-pagina als volgt:

Application("key") = value
Dim value As Object = Application("key")

De gegevenscache biedt een veel uitgebreidere API voor het opslaan van gegevens in cache, het bieden van mechanismen voor op tijd en afhankelijkheid gebaseerde expiries, prioriteiten voor cache-items, enzovoort. Met statische leden en toepassingsstatus moeten dergelijke functies handmatig worden toegevoegd door de paginaontwikkelaar. Wanneer gegevens in de cache worden opgeslagen tijdens het opstarten van de toepassing voor de gehele levensduur van de toepassing, zijn de voordelen van de gegevenscache echter irrelevant. In deze zelfstudie bekijken we code die gebruikmaakt van alle drie de technieken voor het opslaan van statische gegevens in de cache.

Stap 3: De tabelgegevens opslaan in deSupplierscache

De Northwind-databasetabellen die we tot nu toe hebben geïmplementeerd, bevatten geen traditionele opzoektabellen. De vier DataTables die in onze DAL zijn geïmplementeerd, zijn alle modeltabellen waarvan de waarden niet statisch zijn. In plaats van de tijd te besteden aan het toevoegen van een nieuwe gegevenstabel aan de DAL en vervolgens een nieuwe klasse en methoden aan de BLL, laten we in deze zelfstudie doen alsof de gegevens van de Suppliers tabel statisch zijn. Daarom kunnen we deze gegevens opslaan bij het opstarten van de toepassing.

Als u wilt beginnen, maakt u een nieuwe klasse met de naam StaticCache.cs in de CL map.

De StaticCache.vb-klasse maken in de map CL

Afbeelding 2: De StaticCache.vb klasse maken in de CL map

We moeten een methode toevoegen waarmee de gegevens bij het opstarten worden geladen in het juiste cachearchief, evenals methoden die gegevens uit deze cache retourneren.

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Private Shared suppliers As Northwind.SuppliersDataTable = Nothing
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using a static member variable
        Dim suppliersBLL As New SuppliersBLL()
        suppliers = suppliersBLL.GetSuppliers()
    End Sub
    
    <DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return suppliers
    End Function
End Class

In de bovenstaande code wordt een statische lidvariabele suppliersgebruikt om de resultaten van de SuppliersBLL klassemethode GetSuppliers() op te halen, die wordt aangeroepen vanuit de LoadStaticCache() methode. De LoadStaticCache() methode moet worden aangeroepen tijdens het starten van de toepassing. Zodra deze gegevens zijn geladen bij het opstarten van de toepassing, kan elke pagina die moet werken met leveranciersgegevens de StaticCache-methode van de GetSuppliers()-klasse aanroepen. Daarom wordt de database slechts één keer aangeroepen om de leveranciers op te halen, bij het starten van de toepassing.

In plaats van een statische lidvariabele te gebruiken als cacheopslag, kunnen we ook de toepassingsstatus of de gegevenscache gebruiken. De volgende code toont de klasse die opnieuw is gebruikt voor het gebruik van de toepassingsstatus:

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using application state
        Dim suppliersBLL As New SuppliersBLL()
        HttpContext.Current.Application("key") = suppliers
    End Sub
    
    <DataObjectMethodAttribute(DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return TryCast(HttpContext.Current.Application("key"), _
            Northwind.SuppliersDataTable)
    End Function
End Class

In LoadStaticCache()worden de leveranciersgegevens opgeslagen in de sleutel van de toepassingsvariabele. Het wordt als het juiste type (Northwind.SuppliersDataTable) geretourneerd van GetSuppliers(). Hoewel de toepassingsstatus kan worden geopend in de code-behind-klassen van ASP.NET-pagina's met behulp van Application("key"), moeten we in de architectuur HttpContext.Current.Application("key") gebruiken om de huidige HttpContext te verkrijgen.

Op dezelfde manier kan de gegevenscache worden gebruikt als een cacheopslag, zoals in de volgende code wordt weergegeven:

<System.ComponentModel.DataObject()> _
Public Class StaticCache
    Public Shared Sub LoadStaticCache()
        ' Get suppliers - cache using a static member variable
        Dim suppliersBLL As New SuppliersBLL()
        HttpRuntime.Cache.Insert("key", suppliers, Nothing, _
            Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, _
            CacheItemPriority.NotRemovable, Nothing)
    End Sub
    <System.ComponentModel.DataObjectMethodAttribute_
    (System.ComponentModel.DataObjectMethodType.Select, True)> _
    Public Shared Function GetSuppliers() As Northwind.SuppliersDataTable
        Return TryCast(HttpRuntime.Cache("key"), Northwind.SuppliersDataTable)
    End Function
End Class

Als u een item wilt toevoegen aan de gegevenscache zonder verlooptijd, gebruikt u de System.Web.Caching.Cache.NoAbsoluteExpiration en System.Web.Caching.Cache.NoSlidingExpiration waarden als invoerparameters. Deze specifieke overload van de Insert-methode voor de gegevenscache is geselecteerd zodat we de prioriteit van het cache-item kunnen opgeven. De prioriteit wordt gebruikt om te bepalen welke items uit de cache moeten worden verwijderd wanneer het beschikbare geheugen laag is. Hier gebruiken we de prioriteit NotRemovable, die ervoor zorgt dat dit cache-item niet wordt verwijderd.

Opmerking

Deze tutorial implementeert de StaticCache klasse door de benadering van de statische lidvariabele te gebruiken. De code voor de toepassingsstatus- en gegevenscachetechnieken is beschikbaar in de opmerkingen in het klassebestand.

Stap 4: Code uitvoeren bij het opstarten van de toepassing

Als u code wilt uitvoeren wanneer een webtoepassing voor het eerst wordt gestart, moet u een speciaal bestand maken met de naam Global.asax. Dit bestand kan gebeurtenis-handlers bevatten voor gebeurtenissen op toepassings-, sessie- en aanvraagniveau. Hier kunnen we code toevoegen die wordt uitgevoerd wanneer de toepassing wordt gestart.

Voeg het Global.asax bestand toe aan de hoofdmap van uw webtoepassing door met de rechtermuisknop te klikken op de naam van het websiteproject in Visual Studio Solution Explorer en nieuw item toevoegen te kiezen. Selecteer in het dialoogvenster Nieuw item toevoegen het itemtype Globale toepassingsklasse en klik vervolgens op de knop Toevoegen.

Opmerking

Als u al een Global.asax bestand in uw project hebt, wordt het itemtype Globale toepassingsklasse niet weergegeven in het dialoogvenster Nieuw item toevoegen.

Het global.asax-bestand toevoegen aan de hoofdmap van uw webtoepassing

Afbeelding 3: Voeg het bestand toe aan de Global.asax hoofdmap van uw webtoepassing (klik hier om de volledige afbeelding weer te geven)

De standaardbestandssjabloon Global.asax bevat vijf methoden binnen een tag aan de serverzijde <script> :

  • Application_Start wordt uitgevoerd wanneer de webtoepassing voor het eerst wordt gestart
  • Application_End wordt uitgevoerd wanneer de toepassing wordt afgesloten
  • Application_Error wordt uitgevoerd wanneer een niet-verwerkte uitzondering de toepassing bereikt
  • Session_Start wordt uitgevoerd wanneer een nieuwe sessie wordt gemaakt
  • Session_End wordt uitgevoerd wanneer een sessie is verlopen of afgetrokken

De Application_Start gebeurtenis-handler wordt slechts één keer aangeroepen tijdens de levenscyclus van een toepassing. De toepassing start de eerste keer dat een ASP.NET resource wordt aangevraagd vanuit de toepassing en blijft actief totdat de toepassing opnieuw wordt opgestart. Dit kan gebeuren door de inhoud van de /Bin map te wijzigen, Global.asaxde inhoud in de App_Code map te wijzigen of het Web.config bestand te wijzigen, onder andere oorzaken. Raadpleeg ASP.NET Overzicht van de levenscyclus van toepassingen voor een gedetailleerdere bespreking van de levenscyclus van de toepassing.

Voor deze tutorials hoeven we alleen code toe te voegen aan deze Application_Start methode, dus u kunt de anderen verwijderen. Roep in Application_Start gewoon de StaticCache klasse's LoadStaticCache() methode aan, waarmee de informatie van de leverancier wordt geladen en in de cache wordt geplaatst.

<%@ Application Language="VB" %>
<script runat="server">
    Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
        StaticCache.LoadStaticCache()
    End Sub
</script>

Dat is alles! Bij het opstarten van de toepassing haalt de LoadStaticCache() methode de leveranciersgegevens van de BLL op en slaat deze op in een statische lidvariabele (of in welk cachearchief u ook in de StaticCache klasse hebt gebruikt). Als u dit gedrag wilt controleren, stelt u een onderbrekingspunt in de Application_Start methode in en voert u uw toepassing uit. Houd er rekening mee dat het onderbrekingspunt wordt bereikt wanneer de toepassing wordt gestart. Volgende aanvragen zorgen er echter niet voor dat de Application_Start methode wordt uitgevoerd.

Een onderbrekingspunt gebruiken om te controleren of de Application_Start gebeurtenis-handler wordt uitgevoerd

Afbeelding 4: Gebruik een onderbrekingspunt om te controleren of de Application_Start gebeurtenis-handler wordt uitgevoerd (klik om de volledige afbeelding weer te geven)

Opmerking

Als u de onderbrekingslijn niet bereikt wanneer u voor het eerst Application_Start met foutopsporing start, kan dit zijn omdat uw toepassing al is gestart. Dwing de toepassing opnieuw op te starten door uw Global.asax of Web.config bestanden te wijzigen en probeer het vervolgens opnieuw. U kunt aan het einde van een van deze bestanden een lege regel toevoegen (of verwijderen) om de toepassing snel opnieuw op te starten.

Stap 5: de gegevens in de cache weergeven

Op dit moment heeft de StaticCache klasse een versie van de leveranciersgegevens die zijn opgeslagen in de cache bij het opstarten van de toepassing die via de GetSuppliers() methode kan worden geopend. Als u met deze gegevens uit de presentatielaag wilt werken, kunt u een ObjectDataSource gebruiken of de methode van de StaticCache klasse GetSuppliers() programmatisch aanroepen vanuit de code-behind-klasse van de ASP.NET-pagina. Laten we eens kijken naar het gebruik van de besturingselementen ObjectDataSource en GridView om de gegevens van de leverancier in de cache weer te geven.

Open eerst de AtApplicationStartup.aspx pagina in de Caching map. Sleep een GridView van de toolbox naar de ontwerper en stel de ID-eigenschap in op Suppliers. Kies vervolgens uit de infotag van GridView om een nieuwe ObjectDataSource met de naam SuppliersCachedDataSourcete maken. Configureer de ObjectDataSource om de StaticCache klasse te gebruiken en de GetSuppliers() methode uit te voeren.

De ObjectDataSource configureren voor het gebruik van de StaticCache-klasse

Afbeelding 5: De ObjectDataSource configureren om de StaticCache klasse te gebruiken (klik om de afbeelding op volledige grootte weer te geven)

Gebruik de methode GetSuppliers() om de leveranciergegevens in de cache op te halen

Afbeelding 6: Gebruik de methode om de leveranciergegevens in de GetSuppliers() cache op te halen (klik hier om de volledige afbeelding weer te geven)

Nadat de wizard is voltooid, worden in Visual Studio automatisch BoundFields toegevoegd voor elk van de gegevensvelden in SuppliersDataTable. De declaratieve markeringen van GridView en ObjectDataSource moeten er ongeveer als volgt uitzien:

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

Afbeelding 7 toont de pagina wanneer deze wordt bekeken via een browser. De uitvoer zou hetzelfde zijn als we de gegevens uit de klasse SuppliersBLL van de BLL hadden gehaald, maar door de StaticCache klasse te gebruiken, worden de leveranciersgegevens geretourneerd zoals ze bij het opstarten van de applicatie zijn gecached. U kunt onderbrekingspunten instellen in de StaticCache klassemethode GetSuppliers() om dit gedrag te verifiëren.

De leveranciergegevens in de cache worden weergegeven in een GridView

Afbeelding 7: De gegevens van de leverancier in de cache worden weergegeven in een GridView (klik om de afbeelding op volledige grootte weer te geven)

Samenvatting

De meeste gegevensmodellen bevatten een evenredige hoeveelheid statische gegevens, meestal geïmplementeerd in de vorm van opzoektabellen. Omdat deze informatie statisch is, is er geen reden om telkens wanneer deze informatie moet worden weergegeven, voortdurend toegang te krijgen tot de database. Bovendien, vanwege de statische aard, wanneer de gegevens in de cache worden opgeslagen, is er geen vervaldatum nodig. In deze handleiding hebben we gezien hoe u dergelijke gegevens kunt cachen in de datacache, de toepassingstoestand en via een statische lidvariabele. Deze informatie wordt in de cache opgeslagen bij het opstarten van de toepassing en blijft gedurende de levensduur van de toepassing in de cache.

In deze zelfstudie en de afgelopen twee hebben we gekeken naar cachegegevens voor de duur van de levensduur van de toepassing en het gebruik van op tijd gebaseerde expiries. Bij het opslaan van databasegegevens in de cache kan een verloopdatum op basis van tijd echter minder zijn dan ideaal. In plaats van de cache periodiek leeg te maken, zou het optimaal zijn om alleen het item in de cache te verwijderen wanneer de onderliggende databasegegevens worden gewijzigd. Dit ideaal is mogelijk door gebruik te maken van SQL-cacheafhankelijkheden, die we in onze volgende zelfstudie gaan onderzoeken.

Veel plezier met programmeren!

Over de auteur

Scott Mitchell, auteur van zeven ASP/ASP.NET-boeken en oprichter van 4GuysFromRolla.com, werkt sinds 1998 met Microsoft-webtechnologieën. Scott werkt als onafhankelijk consultant, trainer en schrijver. Zijn laatste boek is Sams Teach Yourself ASP.NET 2.0 in 24 uur. Hij kan worden bereikt op mitchell@4GuysFromRolla.com.

Speciale dank aan

Deze tutorialreeks is beoordeeld door veel behulpzame beoordelers. Hoofdrecensenten voor deze zelfstudie waren Teresa Murphy en Zack Jones. Bent u geïnteresseerd in het bekijken van mijn aanstaande MSDN-artikelen? Zo ja, laat iets van je horen via mitchell@4GuysFromRolla.com.