Geschrieben von: Christian Holm
Kategorie: ASP.NET
This printed page brought to you by AlphaSierraPapa
Eine dynamische Seite zu cachen ist bei vielen gleichzeitigen Userzugriffen ganz praktisch und spart vor allem Web Server Resourcen. Bei komplexeren dynamischen Seiten kann es aber vorkommen, daß der dynamische Content unterschiedliche "Verfallsdaten" haben kann. Mit ASP.NET haben Sie nun die Möglichkeit einzelne Regionen einer Seite mit Hilfe von ASP.NET User Controls (vormals ASP+ Pagelets) die Content Expiration individuell an den dynamisch generierten Content anzupassen. Dieser Artikel soll Ihnen einen Überblick über die ASP.NET Fragment Caching Funktionalität bieten.
Im Artikel Output Caching 101 haben Sie die Grundfunktionalität des Output Cachings kennengelernt. Nun geht es einen Schritt weiter - dieser Artikel zeigt Ihnen anhand von Beispielen wie man nun einzelne Regionen einer ASP.NET Seite mit unterschiedlichen Duration-Attributwerten versehen kann, um den jeweiligen Content nach Ablauf einer unabhängigen Zeitspanne erneut in den Cache abzulegen.
Wie die Beispiele des Output Caching 101 Artikels gezeigt haben, ist das Caching mit der OutputCache Directive zu aktivieren. Ähnlich wie bei der Page Directive darf diese nur genau einmal in einer Web Site vorkommen. Daher muß man sich mit ASP.NET User Controls (vormals ASP+ Pagelets) behelfen um so den Content verschiedene Expiration-Periods zuzuweisen.
Als erstes Beispiel habe ich eine dynamische Befüllung einer DropDownList Web Control gewählt. Der Content der Control wird aus der Northwind SQL Datenbank geholt. Dabei läuft der Content der Control, welcher im Cache angelegt ist, in einer Minute ab. Innerhalb dieser Zeit können beliebig oft Postbacks durchgeführt werden, die Listeneinträge der Control werden immer aus dem Cache geholt (die Cache-Location ist hier nicht näher definiert), und es wird nicht andauernd auf die Datenbank zugegriffen. Dies spart einiges an Serverresourcen und da hier das Caching auch serverseitig möglich ist, können somit auch mehrere User gleichzeitig aus dem Servercache-Repository bedient werden.
Da wir User Controls verwenden, erstellen wir für das Beispiel zwei Dateien (aspx und ascx). Zuerst eine .aspx Datei mit dem Namen FragCachedUsrCtrl.aspx. Diese enthält die Referenz auf unsere spätere User Control und die Einbindung derer:
<%@ Register TagPrefix="DataUsrCtrl" TagName="MyDropDownListSuppliers" Src="MyDropDownListSuppliers.ascx" %> <html> <script language="C#" runat="server"> void Page_Load(Object Src, EventArgs E ) { TimeStamp.Text = DateTime.Now.ToString(); } </script> <body> <form runat=server> <h3>Select Shippers</h3> <DataUsrCtrl:MyDropDownListSuppliers runat="server"/> <p> Page Generated at: <asp:label id="TimeStamp" runat="server" /> </p> </form> </body> </html>
Zusätzlich zur eigentlichen DropDownList Control wird hier eine TimeStamp (ASP.NET Label Control TimeStamp) erstellt, die bei jedem Postback der Seite das Datum und Uhrzeit des Servers angibt. Damit können wir auf einfache Art und Weise das partielle Caching der Seite überprüfen. Die eigentliche Arbeit (das dynamische Befüllen der DropDown List Control) wird, wie erwähnt von unserer gecachten User Control (MyDropDownListSuppliers.ascx) durchgeführt:
<%@ OutputCache Duration="60" VaryByParam="none"%> <%@ Import Namespace="System.Data" %> <%@ Import Namespace="System.Data.SqlClient" %> <script language="C#" runat="server"> void Page_Load(Object sender, EventArgs e) { if(!Page.IsPostBack) { string strSqlQuery = "SELECT CompanyName, SupplierID FROM Suppliers"; SqlConnection MyConnection = new SqlConnection("server=BLUESCREEN; database=northwind;Trusted_Connection=yes"); SqlDataAdapter MyCommand = new SqlDataAdapter(strSqlQuery, MyConnection); DataSet dsetShippers = new DataSet(); MyCommand.Fill(dsetShippers,"Shippers"); MyDropDownListSuppliers.DataSource = dsetShippers.Tables["Shippers"].DefaultView; MyDropDownListSuppliers.DataTextField = "CompanyName"; MyDropDownListSuppliers.DataValueField = "SupplierID"; MyDropDownListSuppliers.DataBind(); TimeStamp.Text = DateTime.Now.ToString(); } } </script> <p> <asp:DropDownList id="MyDropDownListSuppliers" runat="server" /> Suppliers' Data Accessed at: <asp:label id="TimeStamp" runat="server" /> </p>
Im folgenden Screenshot sehen Sie das Ergebnis des Http-Requests auf die FragCachedUsrCtrl.aspx Datei. Zusätzlich auch das Ergebnis wenn von einem anderen Client aus zugegriffen wird:
Wie Sie unschwer an den unterschiedlichen TimeStamps sehen können, werden die Daten aus dem Cache bezogen und nicht wiederholt aus der Datenbank. Das war ja nun einfach - Wie das Wort Fragment suggeriert können Sie damit auch mehrere User Controls unabhängig im Cache ablegen. Zunächst die aspx Datei FragCachedUsrCtrMulti.aspx:
<%@ Register TagPrefix="DataUsrCtrl" TagName="MyDropDownListSuppliers" Src="MyDropDownListSuppliers.ascx" %> <%@ Register TagPrefix="DataUsrCtrl" TagName="MyDropDownListProducts" Src="MyDropDownListProducts.ascx" %> <html> <script language="C#" runat="server"> void Page_Load(Object Src, EventArgs E ) { TimeStamp.Text = DateTime.Now.ToString(); } </script> <body> <form runat=server> <h3>Select Suppliers</h3> <DataUsrCtrl:MyDropDownListSuppliers runat="server"/> <h3>Select Products</h3> <DataUsrCtrl:MyDropDownListProducts runat="server"/> <p> Page Generated at: <asp:label id="TimeStamp" runat="server" /> </p> </form> </body> </html>
Es wurde lediglich eine Zeile für die Referenz auf die zusätzliche User Control MyDropDownListProducts.ascx und eine Zeile für deren Aufruf hinzugefügt. Die User Control unterscheidet sich in der Ausführung von der vorig benutzten MyDropDownListSuppliers.ascx nur im Querystring, einer unterschiedlichen Contentexpriation (120 Sekunden statt 60) und die sonst noch nötigen Anpassungen:
<%@ OutputCache Duration="120" VaryByParam="none"%> ... string strSqlQuery = "SELECT ProductID, ProductName FROM Products"; ... <p> <asp:DropDownList id="MyDropDownListProducts" runat="server" /> Products' Data Accessed at: <asp:label id="TimeStamp" runat="server" /> </p>
Im Browser sieht man die unterschiedlichen Contentexpirationzeiten anhand der jeweiligen TimeStamps:
Daß dies nicht nur zufällige Ergebnisse sind, sieht man am Pagerenderingvorgang, den man durch das True-setzen des Trace Attributs der Page Directive erhält:
<%@ Page language="C#" Trace="true"%>
Ergebnis des ersten Http Requests:
Ein paar Sekunden später sieht der Control Tree nur mehr so aus - das Rendern der Dropdownlisten fehlt hier, da ja diese im Cache vorhanden (noch gültig) sind:
Dies war ein schneller und einfacher Einstieg in die neuen Möglichkeiten die das .NET Fragment Caching bietet. Der Programmieraufwand ist gering und der Effekt ist groß - der Datenbankserver wird bei vielen gleichzeitigen Zugriffen deutlich entlastet. Zudem können bei komplexen dynamischen ASP.NET Seiten einzelne Regionen (in Form von eingebundenen User Controls) unabhängig generiert werden.
This printed page brought to you by AlphaSierraPapa
Klicken Sie hier, um den Download zu starten.
http://www.aspheute.com/code/20011009.zip
ASP.NET User Controls im Einsatz
http:/www.aspheute.com/artikel/20001114.htm
Einstieg in Visual Studio.NET - die erste Webanwendung mit Visual C#
http:/www.aspheute.com/artikel/20031010.htm
Output Caching 101
http:/www.aspheute.com/artikel/20011008.htm
©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.