自定義緩存控件html
前面咱們介紹了經過查詢參數實現緩存一個或多個頁面,其實ASP.NET也容許咱們自定義緩存方式來決定是否緩存頁或重用現有的,這時咱們能夠經過設置VaryByCustom屬性來實現。web
假設,如今咱們要設計基於不一樣UserHostName的緩存,因爲程序在執行過程當中,首先調用GetVaryByCustomString()方法來肯定是否緩存頁面或重用現有的,因此咱們能夠經過重寫該方法實現基於UserHostName的緩存,具體實現以下:ajax
- /// <summary>
- /// Gets vary cache based on custom string value.
- /// </summary>
- /// <param name="context">Http context.</param>
- /// <param name="custom">custom string</param>
- /// <returns></returns>
- public override string GetVaryByCustomString(HttpContext context, string custom)
- {
- if (string.Equals(custom, "UserHostName", StringComparison.OrdinalIgnoreCase))
- {
- // Indicates that the cache should be vary on user host name.
- return Context.Request.UserHostName;
- }
- return base.GetVaryByCustomString(context, custom);
- }
前面咱們重寫了GetVaryByCustomString()方法,使得UserHostName值不一樣時,獲取相應的緩存值。數據庫
而後讓程序基於UserHostName建立緩存,因此咱們要在頁面添加如下代碼:json
- <!-- set vary cache based on custom string value -->
- <%@ OutputCache Duration="30" VaryByParam="None" VaryByCustom="UserHostName" %>
咱們經過自定義如今GetVaryByCustomString()方法,實現了Web程序根據UserHostName實施不一樣的緩存方式,其實,咱們還能夠實現更多種類緩存方案,例如:基於用戶角色、時間和Url等等。api
片斷緩存緩存
在某些狀況下,咱們不能緩存整個頁面,但咱們仍想緩存部分頁面從而減輕系統的負擔;其實,咱們能夠經過兩種方法實現:片斷緩存和數據緩存.安全
爲了實現片斷緩存,咱們須要建立自定義控件緩存部分頁面,而後咱們把OutputCache指令添加到自定義控件中,這樣整個頁面將不會被緩存,而自定義緩存控件除外。app
前面咱們介紹了輸出緩存的使用,只需在頁面中添加OutputCache指令,假設咱們要在幾個頁面中添加輸出緩存這可能比較簡單,但咱們要在幾十個頁面中添加輸出緩存功能,並且前面介紹的例子中Duration屬性值都是直接Hard code到每一個頁面中,若是咱們須要修改Duration屬性值,那麼就必須修改每一個頁面了,ASP.NET還須要從新編譯這些頁面,這不利於咱們的維護,最重要的是增長了咱們的工做量。dom
其實,咱們能夠在web.config文件中定義一個outputCacheProfile(ProductCacheProfile),而後在頁面中添加CacheProfile屬性而且賦值爲ProductCacheProfile,web.config文件設置以下:
- <caching>
- <!-- Sets out put cache profile-->
- <outputCacheSettings>
- <outputCacheProfiles>
- <add name="ProductCacheProfile" duration="30"/>
- </outputCacheProfiles>
- </outputCacheSettings>
- </caching>
如今,咱們在頁面中添加CacheProfile屬性,而且設置爲ProductCacheProfile,以下所示:
- <!-- set CacheProfile property -->
- <%@ OutputCache CacheProfile="ProductCacheProfile" VaryByParam="None" %>
數據緩存
Cache對象是線程安全:這表示無需顯式實現鎖定或解鎖,在添刪Cache對象中的元素,然而,在Cache對象中元素必須是線程安全的。例如,咱們建立一個實體Product,並且存在多個客戶端可能同時操做該對象的狀況,這時咱們必須爲實體Product實現鎖定和解鎖操做(同步操做請參考《單例模式(Singleton)的6種實現》)。
Cache對象中的緩存項自動移除:當緩存過時,依賴項被修改或內存不足緩存ASP.NET會自動移除該緩存項。
緩存項支持依賴關係:咱們能夠給緩存項添加文件、數據庫表或其餘資源類型的依賴關係。
SqlDataSource緩存
當咱們在SqlDataSource控件中啓用緩存,它緩存SelectCommand中的結果;若是SQL查詢語句中帶有參數時,SqlDataSource控件會緩存每個參數值對應的結果。
這跟咱們以前經過輸出緩存實現報表程序緩存查詢頁面效果同樣,因此咱們將使用SqlDataSource緩存實現該效果。
假設咱們要提供一個報表程序,讓用戶經過選擇產品名稱(ProductName),獲取相應的產品信息。
首先,咱們在頁面中建立兩個數據源控件:sourceProductName和sourceProduct,接着把數據源分別綁定到Dropdownlist和Gridview中,具體實現以下:
- <!-- The product number datasource START -->
- <asp:SqlDataSource ID="sourceProductName" runat="server" ProviderName="System.Data.SqlClient"
- EnableCaching="True" CacheDuration="3600" ConnectionString="<%$ ConnectionStrings:SQLCONN %>"
- SelectCommand="SELECT ProductNumber FROM Production.Product"></asp:SqlDataSource>
- <!-- The product number datasource END -->
- <!-- The product datasource START -->
- <asp:SqlDataSource ID="sourceProduct" runat="server" ProviderName="System.Data.SqlClient"
- EnableCaching="True" CacheDuration="3600" ConnectionString="<%$ ConnectionStrings:SQLCONN %>"
- SelectCommand="SELECT Name, ProductNumber, SafetyStockLevel, ReorderPoint, StandardCost, DaysToManufacture
- FROM Production.Product WHERE ProductNumber=@ProductNumber">
- <SelectParameters>
- <asp:ControlParameter ControlID="ddlProductNumber" Name="ProductNumber" PropertyName="SelectedValue" />
- </SelectParameters>
- </asp:SqlDataSource>
- <!-- The product number datasource END -->
- <!-- Binding the product number to gridview control -->
- <!-- NOTE: Due to search and result in the same page, so need to set AutoPostBack is True-->
- <asp:DropDownList ID="ddlProductNumber" AutoPostBack="True" DataSourceID="sourceProductName"
- DataTextField="ProductNumber" runat="server">
- </asp:DropDownList>
- <!-- Binding the product datasource to gridview control -->
- <asp:GridView ID="gvProduct" runat="server" DataSourceID="sourceProduct" CssClass="Product">
- </asp:GridView>
如今咱們對報表程序進行查詢,若是ProudctName以前沒有被緩存起來就會建立相應的緩存,而已經緩存起來的將被重用,查詢結果以下:
緩存的依賴關係
緩存項之間的依賴
ASP.NET Cache容許咱們創建緩存之間的依賴關係,即一個緩存項依賴於另外一個緩存項;如下示例代碼建立了二個緩存項,而且它們之間創建依賴關係。具體實現以下:
- // Creates cache object Key1.
- Cache["Key1"] = "Cache Item 1";
- // Makes Cache["Key2"] dependent on Cache["Key1"].
- string[] dependencyKey = new string[1];
- dependencyKey[0] = "Key1";
- // Creates a CacheDependency object.
- CacheDependency dependency = new CacheDependency(null, dependencyKey);
- // Establishs dependency between cache Key1 and Key2.
- Cache.Insert("Key2", "Cache Item 2", dependency);
如今,當Key1緩存項更新或從緩存中刪除,Key2緩存項就會自動從緩存刪除。
文件依賴
前面咱們介紹了緩存項之間的依賴關係,ASP.NET Cache還提供緩存項與文件之間的依賴關係,當文件被更新或刪除對應的緩存項也將失效。
在上篇博文《Ajax與JSON的一些總結》的最後介紹的一個DEMO——Weibo Feed中,咱們經過實時方式向新浪微博API發送請求獲取相應的數據,但在必定時間內請求的次數是有限制的,一旦超出了限制次數就再也不接受請求了(具體請參考Rate-limiting)。因此能夠經過Cache的方式把數據緩存起來,當客戶端請求時,若是緩存數據已經存在那麼直接返回數據,不然從新想微博API請求數據。
首先,咱們建立一個HttpHandler,它負責向微博API發送請求而且把數據保存的文件中,最後把數據返回的客戶端。
接下來,咱們定義CacheData()方法把微博數據保存到文本文件中而且創建緩存與數據文件的依賴關係。
- /// <summary>
- /// Caches the data into text file.
- /// </summary>
- /// <param name="context">The http context</param>
- private void CacheData(HttpContext context)
- {
- // Weibo API.
- string uri = context.Request.QueryString["api"] + "?" +
- "source=" + context.Request.QueryString["source"] + "&" +
- "count=" + context.Request.QueryString["count"];
- HttpWebResponse response = this.GetWeibos(uri);
- if (null == response)
- {
- throw new ArgumentNullException("Response is null");
- }
- string jsonData;
- // Writes the reponse data into text file.
- using (var reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(response.CharacterSet)))
- {
- jsonData = reader.ReadToEnd();
- }
- string dataPath = context.Server.MapPath("weibo.json");
- using (var writer = new StreamWriter(dataPath, false, Encoding.GetEncoding(response.CharacterSet)))
- {
- writer.Write(jsonData);
- }
- // Establishs dependency between cache weibo and text file.
- // Sets cache expires after 2 minuntes.
- HttpRuntime.Cache.Insert("weibo", jsonData, Dep, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(2));
- }
如今咱們把數據保存到文本文件中而且創建了緩存weibo與數據文件的依賴關係,接下來咱們要把JSON格式數據返回給客戶端。
- /// <summary>
- /// Responses the weibo data.
- /// </summary>
- /// <param name="context">The http contex.</param>
- private void ResponseWeibo(HttpContext context)
- {
- // Gets the weibo cache data.
- byte[] buf = Encoding.UTF8.GetBytes(HttpRuntime.Cache["weibo"].ToString());
- // Writes the data into output stream.
- context.Response.OutputStream.Write(buf, 0, buf.Length);
- context.Response.OutputStream.Flush();
- ////context.Response.Close();
- }
上面咱們把JSON格式字符串轉換爲Byte數值,而後寫入到OutputStream中,最後把數據返回給客戶端。
- // The function to get weibo data.
- loadWeibo: function() {
- $.ajax({
- // Weibo API.
- url: "WeiboHandler.ashx",
- type: "GET",
- // NOTE: We get the data from same domain,
- // dataType is json.
- dataType: "json",
- data: {
- source: JQWeibo.appKey,
- count: JQWeibo.numWeibo
- },
- // When the requet completed, then invokes success function.
- success: function(data, textStatus, xhr) {
- // Sets html structure.
- var html =
- '<div class="weibo">' +
- '<a href="http://weibo.com/DOMAIN" target="_blank">USER</a>' +
- ':WEIBO_TEXT<div class="time">AGO</div>';
- // Appends weibos into html page.
- for (var i = 0; i < data.length; i++) {
- $(JQWeibo.appendTo).append(
- html.replace('WEIBO_TEXT', JQWeibo.ify.clean(data[i].text))
- // Uses regex and declare DOMAIN as global, if found replace all.
- .replace(/DOMAIN/g, data[i].user.domain)
- .replace(/USER/g, data[i].user.screen_name)
- .replace('AGO', JQWeibo.timeAgo(data[i].created_at))
- );
- }
- }
- })
- }
總結緩存可使應用程序的性能獲得很大的提升,所以在設計應用程序應該予以考慮,本博文主要介紹了ASP.NET中輸出緩存和數據緩存的應用場合和區別。
頁面緩存適用於生成的頁面一般都相同或改變時間比較固定狀況,例如:數據在每小時都會更新,那麼咱們能夠設置duration爲3600s。
數據緩存適用生成的頁面老是在變化狀況。
http://www.codeproject.com/Articles/29899/Exploring-Caching-in-ASP-NET
http://msdn.microsoft.com/zh-cn/library/aa478965.aspx#XSLTsection129121120120
http://www.amazon.com/Beginning-ASP-NET-3-5-2008-Professional/dp/1590598911
原文連接:http://www.cnblogs.com/rush/archive/2012/06/30/2571438.html