ASP.NET 2.0緩存技術探討
1.ASP.NET Output Caching
當一個網頁頻繁被訪問的時候,我們可以通過把整個網頁緩存來提高執行效率。這樣作的優點是,當用戶再次訪問這個網頁的時候,被格式化好的HTML會被直接送顯。
為什么會存在這種效果呢?我們通過ASP.NET的基本運行機制來解釋這個問題。ASP.NET是一個動態的服務器,當用戶從客戶端提供一個請求的時候,那么服務端的IIS接受到請求,然后根據用戶的提示執行相應的代碼。執行代碼之后生成一個結果。這個結果會被緩存成一個HTML放在Server端,然后通過響應用戶的Request將這個HTML傳送到客戶端。在這之中我們發現,很多時候,用戶的請求實際上并沒有多大的變化,可能請求的都是相同的內容。這時候執行一次代碼的成本就會相當的高。既然我們已經生成了一個HTML,我們何必要在重新執行一次代碼呢?我們直接把HTML送顯就可以了。
◆Output Cache是一項非常有效的增強訪問性能的技術,由于IIS的一些特性,默認情況下Output Cache是打開的,但是要對一些請求進行緩存,還需要開發者進行定制。
◆定制Output Caching
對于Output Caching的定制,我們有兩種方法,一種是基于底層的API技術,一種是基于高層的@Output Caching,一旦Output Caching被定制過,那么這個網頁就會在第一次被訪問的時候生成cache,直到請求過期為止。
我們著重點是使用高層的@Output Caching標簽來設置,因為API技術的編程難度比較大,和ASP.NET快速編程理念不相符。
◆代碼示例:通過使用Output Cache定義一個緩存頁,顯示當前時間,大家可以看到,當這個頁面被緩存之后,刷新時,當前時間顯示不發生變化。
<script runat="server">protected void Page_Load(object sender, EventArgs e)
{
TimeMsg.Text = DateTime.Now.ToString();
}
</script>//head以前。
protected void Page_Load(object sender, EventArgs e)
{
TimeMsg.Text = DateTime.Now.ToString();
}
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>
◆示例講解
在這個頁面中<%@ Output Cache Duration = “60” VaryByParam = “none”%>
這段話定義了頁面將要被緩存,并且,其緩存時間為60秒,并在一個頁面被緩存之后,通過定義VaryByParam屬性,它不會因為request接受的參數而改變,只有在60秒之后,頁面自動清除緩存,此時,第一個訪問提供了新的緩存。
◆代碼示例:數據訪問的小示例,相對顯示當前數據示例,這個示例更能顯示緩存頁之后刷新的性能優勢。
<script runat="server">protected void Page_Load(object sender, EventArgs e)
{
TimeMsg.Text = DateTime.Now.ToString();
}
</script>//head以前。
protected void Page_Load(object sender, EventArgs e)
{
TimeMsg.Text = DateTime.Now.ToString();
}
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<%@ OutputCache Duration="60" VaryByParam="none" %>//最上面
◆由參數改變緩存內容
有些時候我們需要根據用戶的請求來生成頁面,但是用戶的請求只有有限的幾種組合,這個時候就可以根據用戶請求來生成幾種緩存頁面,來進行緩存。
◆代碼示例:接受參數示例,根據用戶選擇不同的Name顯示不同的數據庫內容。
最開始部分:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %><%@ OutputCache Duration="60" VaryByParam="Name" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
TimeMsg.Text = DateTime.Now.ToString("G");
}
</script>
Body內容:
<span style="font-family: Verdana">Using the Output Cache</span><b>Authors by Name:</b>
<table cellpadding="3" cellspacing="0" rules="all" style="border-left-color: black;
border-bottom-color: black; width: 700px; border-top-color: black; border-collapse: collapse;
background-color: #aaaadd; border-right-color: black">
<tr>
<td>
<a href="Default.aspx?Name=李陽">1</a></td>
<td>
<a href="Default.aspx?Name=陳勝">2</a></td>
<td>
<a href="Default.aspx?Name=夏秘密">3</a></td>
<td>
<a href="Default.aspx?Name=范玲玲">4</a></td>
</tr>
</table>
<br />
<asp:GridView ID="GridView1" runat="server" DataSourceID="SqlDataSource1">
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:qimuConnectionString %>"
SelectCommand="SELECT * FROM [tab1] WHERE ([Name] = @Name)">
<SelectParameters>
<asp:QueryStringParameter Name="Name" QueryStringField="Name" DefaultValue="李陽" />
</SelectParameters>
</asp:SqlDataSource>
<br />
<em>Last generated on:</em>
<asp:Label ID="TimeMsg" runat="server"></asp:Label>
顯示效果:
Using the Output CacheAuthors by Name:
ID |
Name |
Sex |
1 |
李陽 |
男 |
Last generated on: 2009-5-10 0:29:13
◆接受參數示例解說
關鍵語句<%@ Output Cache Duration = “60” VaryByParam = “Name”%>
上面顯示一個數據庫查詢示例,并在頁面下端放置一個訪問的當前時間顯示,可以清楚的看到,對于每個不同的參數,一分鐘之內的訪問會得到同一個時間戳,這表明用戶在這個時間內訪問的視同一個cache。
注意:不足是在60秒以內數據庫做出改變,不能顯示更新的顯示,需要處理這個問題還需要其他的設置。
◆硬盤Output Cache
默認情況下,Output Cache會被緩存到硬盤上。我們可以通過修改diskcacheenable的屬性來設置其是否緩存,還可以通過在web config里配置緩存文件的大小。
在使用程序的時候,我們常用內存緩存和交換區緩存,硬盤緩存技術我們可能用的不是很多,因為覺得硬盤速度慢,或者交互起來有問題。實際上,由于服務器現在占用內存都比較多,尤其是大型的應用。所以在IIS服務默認是把硬盤服務是打開的。
◆使用DiskOutput Cache示例:
<%@ OutputCache Duration="3600" VaryByParam="name" DiskCacheable="true" %>Web.Config文件中,
<configuration>
<appSettings/>
<system.web>
<caching>
<outputCache>
<diskCache enabled="true" maxSizePerApp="2"(2M) />
</outputCache>
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheFor60Seconds" duration="60" />
</outputCacheProfiles>
</outputCacheSettings>
<!--
<sqlCacheDependency enabled="true" pollTime="1000" >
<databases>
<add name="PubsDB" connectionStringName="pubsConnectionString" />
</databases>
</sqlCacheDependency>
-->
</caching>
</system.web>
</configuration>
設置DiskOutput屬性。
指定硬盤緩存時,指定時間要相應的大一些。硬盤訪問速度相對慢一點。(VS 2005正式版已經刪除了這一個功能,汗!)
◆回調緩存
通過設置回調緩存機制,可以針對每個請求在頁面中插入動態的部分,以彌補單獨使用靜態緩存的不足。
代碼示例:
回調緩存示例
<%@ Page Language="VB" %><%@ OutputCache Duration="60" VaryByParam="none" %>
<script runat="server">
Shared Function GetCurrentDate(ByVal context As HttpContext) As String
Return Now.ToString()
End Function
</script>
<html>
<head id="Head1" runat="server">
<title>Post Cache Substitution</title>
</head>
<body>
<form id="form1" runat="server">
<h4>
This page uses post cache substitution to insert a dynamic value into a cached page.</h4>
<p>
Time:
<%= DateTime.Now.ToString() %>
</p>
<p>
<b>Real Time:
<asp:Substitution ID="Substitution1" runat="server" MethodName="GetCurrentDate" />
</b>
</p>
</form>
</body>
</html>
通過API實現回調緩存
<%@ Page Language="VB" %><%@ OutputCache Duration="60" VaryByParam = "none" %>
<script runat="server">
Shared Function GetCurrentDate(context As HttpContext) As String
return DateTime.Now.ToString()
End Function
</script>
<html>
<head id="Head1" runat="server">
<title>Post Cache Substitution</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<b>This page uses post cache substitution to insert a dynamic value into a cached page.</b>
<br /><br />
Time: <%= DateTime.Now.ToString() %>
<br /><br />
<b>
Real Time: <% Response.WriteSubstitution(New HttpResponseSubstitutionCallback(AddressOf GetCurrentDate)) %>
</b>
</div>
</div>
</form>
</body>
</html>
通過使用SubStitution來實現緩存
◆使用API定制緩存
如果需要對緩存進行更詳細的設置,可以通過設置System.Web.HttpCachePolicy屬性來進行配置下面這個語句和我們
<%@ Output Cache Duration = “60” VaryByParam = “none”%>完全一樣 |
2.Page Fragment Caching
◆作為Output的緩存的附加功能,還提供一種緩存技術,專門用于緩存用戶控件或者網頁中的一部分東西。可以指定沒一部分或者某一個區域不被緩存。
◆在頁面中,指定返回參數,來決定控件被緩存的部分。使用語句VaryByparam語句指定控件更具參數來改變。
◆示例:通過返回參數改變緩存內容示例
用戶控件頁面設置:
<%@ Control Language="vb" %><%@ OutputCache Duration="60" VaryByParam="none" %>
調用控件頁面設置:
<%@ Register TagPrefix="Acme" TagName="DataControl" Src="datactrl.ascx" %>
Body部分:
<h3>
<font face="Verdana">Fragment Caching</font></h3>
<Acme:DataControl runat="server" />
<br>
<i>頁面最后被訪問于:</i>
<asp:Label ID="TimeMsg" runat="server" />
◆接受控件傳參數修改
緩存用戶控件同樣還可以使用控件作為參數來源。通過指定控件作為緩存控件的參數來源,可以達到緩存控件數據的目的。
示例:通過控件參數改變緩存內容示例
用戶控件頁面設置:
<%@ Control Language="VB" ClassName="FragCtrlwithAPI" %><%@ OutputCache Duration="60" VaryByControl="pickstate" %>
<script runat="server">
Private duration As TimeSpan
Sub Page_Load(ByVal sender As Object, ByVal E As EventArgs)
If (pickstate.SelectedValue = "CA") Then
duration = New TimeSpan(0, 0, 10)
CachePolicy.Duration = duration
End If
End Sub
Sub Page_PreRender(ByVal sender As Object, ByVal e As EventArgs)
Label1.Text = Now.ToString("G")
Label2.Text = Now.Add(CachePolicy.Duration).ToString("G")
End Sub
</script>
<div style="border: dotted 1px blue; padding: 5px; background-color: #eeeeee;">
<asp:DropDownList ID="pickstate" runat="server" AutoPostBack=true>
<asp:ListItem Text="CA" Value="CA" />
<asp:ListItem Text="UT" Value="UT" />
<asp:ListItem Text="MD" Value="MD" />
<asp:ListItem Text="OR" Value="OR" />
<asp:ListItem Text="MI" Value="MI" />
<asp:ListItem Text="TN" Value="TN" />
</asp:DropDownList>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:pubsConnectionString %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] where state=@state"
ProviderName="System.Data.SqlClient">
<SelectParameters>
<asp:ControlParameter ControlID="pickstate" DefaultValue="CA" Name="state" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:GridView ID="GridView1" runat="server" DataSourceID="sqldatasource1" />
<p>
控件被建立于<asp:Label ID="Label1" runat="server" Text="Label"/><br />
控件被銷毀<asp:Label ID="Label2" runat="server" Text="Label"/><br />
</p>
</div>
調用控件頁面設置:
<%@ Register Src="datactrlnew.ascx" TagName="FragCtrl" TagPrefix="acme" %>
Body部分:
<acme:FragCtrl ID="FragCtrl1" runat="server" />
當前時間:
<%=Now.ToString("G") %>
<asp:Button ID="Button2" runat="server" Text="Refresh" />
3.Data Caching(數據緩存)
◆ASP.NET提供了一種非常快捷的方法進行數據庫緩存,用戶可以非常方便的對頁面變量進行緩存。并以此提高程序效率。
◆一個頁面變量的緩存生命周期與應用程序的緩存生命周期相同。
◆同時對后臺數據進行修改的時候,還需要對Cache進行相應的處理。
◆示例:使用數據緩存示例:
<%@ Page Language="vb" %><%@ Import Namespace="System.Data" %>
<%@ Import Namespace="System.Data.SqlClient" %>
<html>
<script runat="server">
Sub Page_Load(ByVal Src As Object, ByVal E As EventArgs)
Dim Source As DataView
' try to retrieve item from cache
' if it's not there, add it
Source = Cache("MyDataSet")
If Source Is Nothing Then
Dim MyConnection As SqlConnection
Dim MyCommand As SqlDataAdapter
MyConnection = New SqlConnection(ConfigurationManager.ConnectionStrings("pubsConnectionString").ConnectionString)
MyCommand = New SqlDataAdapter("select * from Authors", MyConnection)
Dim ds As New DataSet
MyCommand.Fill(ds, "Authors")
Source = New DataView(ds.Tables("Authors"))
Cache("MyDataSet") = Source
CacheMsg.Text = "Dataset created explicitly"
Else
CacheMsg.Text = "Dataset retrieved from cache"
End If
MyGrid.DataSource = Source
MyGrid.DataBind()
End Sub
</script>
<body>
<form id="Form1" runat="server">
<h3>
<font face="Verdana">Caching Data</font></h3>
<asp:GridView ID="MyGrid" runat="server">
</asp:GridView>
<p>
<i>
<asp:Label ID="CacheMsg" runat="server" /></i>
</p>
</form>
</body>
</html>
4.SQL Cache
前面的例子中,我們使用的是緩存技術,一旦時間到,無論服務器端的數據是否改變都會釋放緩存,下面介紹的例子,通過配置數據庫連接池,只有當數據庫數據被改變的時候,緩存才會改變。
示例:配置連接池示例
開一個DOS窗口->找到aspnet_regsql.exe工具(常用參數:-s指定我們注冊的服務器-E使用Windows授權模式-D指定數據庫DataBase名字-ED緩存生效)->
aspnet_regsql.exe –s “.SQLExPress” –E –d “pubs” –ed |
5.Cache Configuration
可以通過在webconfig里配置不同的緩存描述,在頁面中調用該描述來減少重復定義緩存描述的工作量。
示例:緩存描述定義示例:
<configuration><appSettings/>
<system.web>
<caching>
<outputCache>
<diskCache enabled="true" maxSizePerApp="2"(2M) />
</outputCache>
<outputCacheSettings>
<outputCacheProfiles>
<add name="CacheFor60Seconds" duration="60" />
</outputCacheProfiles>
</outputCacheSettings>
<!--
<sqlCacheDependency enabled="true" pollTime="1000" >
<databases>
<add name="PubsDB" connectionStringName="pubsConnectionString" />
</databases>
</sqlCacheDependency>
-->
</caching>
</system.web>
</configuration>
6.總結
◆Output Caching
◆Fragment Caching
◆Data Caching
◆SQL Cache
◆Cache Configuration
【編輯推薦】