Asp.Net 基礎知識回顧_Cache

1、傳統緩存方式html

好比將可重複利用的東西放到Application或是Session中去保存。web

 Session["Count"] = 100;sql

 Application["Count"] = 100;數據庫

2、頁面輸出緩存編程

頁面輸出緩存是最爲簡單的緩存機制,該機制將整個ASP.NET頁面內容保存在服務器內存中。當用戶請求該頁面時,系統從內存中輸出相關數據,直到緩存數據過時。在這個過程當中,緩存內容直接發送給用戶,而沒必要再次通過頁面處理生命週期。一般狀況下,頁面輸出緩存對於那些包含不須要常常修改內容,須要大量處理才能編譯完成的頁面特別有用。須要注意的是,頁面輸出緩存是將頁面所有內容都保存在內存中,並用於完成客戶端請求。數組

設置頁面輸出緩存可使用如下兩種方式:一種是使用@OutputCache指令,另外一種是使用頁面輸出緩存API。頁面輸出緩存API主要是指HttpCachePolicy類。瀏覽器

@ OutputCache以聲明的方式控制 ASP.NET 頁或頁中包含的用戶控件的輸出緩存策略。緩存

語法以下:服務器

<%@ OutputCache Duration="#ofseconds"
   Location="Any | Client | Downstream | Server | None | ServerAndClient "
   Shared="True | False"
   VaryByControl="controlname"
   VaryByCustom="browser | customstring"
   VaryByHeader="headers"
   VaryByParam="parametername" 
   CacheProfile="cache profile name | ''"
   NoStore="true | false"
   SqlDependency="database/table name pair | CommandNotification"
%>

Duration網絡

頁或用戶控件進行緩存的時間(以秒計)。在頁或用戶控件上設置該屬性爲來自對象的 HTTP 響應創建了一個過時策略,並將自動緩存頁或用戶控件輸出。

Location

用於指定輸出緩存項的位置。其屬性值是OutputCacheLocation枚舉值,它們是Any、Client、Downstream、None、Server和ServerAndClient。默認值是Any,表示輸出緩存可用於全部請求,包括客戶端瀏覽器、代理服務器或處理請求的服務器上。須要注意的是,包含在用戶控件中的@OutputCache指令不支持此屬性。

Shared

一個布爾值,肯定用戶控件輸出是否能夠由多個頁共享。默認值爲 false。

NoStore

該屬性定義一個布爾值,用於決定是否阻止敏感信息的二級存儲。須要注意的是,包含在用戶控件中的
@OutputCache指令不支持此屬性。

SqlDependency

    提供了這樣一種能力:當被監測的數據庫中的數據發生變化時,SqlDependency會自動觸發OnChange事件來通知應用程序,從而達到讓系統自動更新數據(或緩存)的目的。

VaryByControl

該屬性使用一個分號分隔的字符串列表,來更改用戶控件的輸出緩存。這些字符串表明在用戶控件中聲明的ASP.NET服務器控件的ID屬性值。除非已經包含了VaryByParam屬性,不然在@ OutputCache指令中,該屬性是必需的。

VaryByCustom

用於自定義輸出緩存要求的任意文本。若是賦予該屬性值是browser,緩存將隨瀏覽器名稱和主要版本信息的不一樣而異。若是輸入了自定義字符串,則必須在應用程序的Global.asax文件中重寫HttpApplication.GetVaryByCustomString方法。

VaryByHeader

該屬性中包含由分號分隔的HTTP標頭列表,用於使輸出緩存發生變化。當將該屬性設爲多標頭時,對於每一個指定的標頭,輸出緩存都包含一個請求文檔的不一樣版本。VaryByHeader屬性在全部HTTP 1.1緩存中啓用緩存項,而不只限於ASP.NET緩存。用戶控件中的@ OutputCache指令不支持此屬性。

3、頁面輸出緩存API

Response類的Cache屬性用於獲取頁面緩存策略,Cache屬性的核心是調用System.Web.HttpCachePolicy。主要用於設置緩存特定的HTTP標頭的方法和用於控制ASP.NET頁面輸出緩存的方法。因爲HttpCachePolicy類方法衆多,下面簡要說明幾個經常使用方法。

SetExpires

用於設置緩存過時的絕對時間。它的參數是一個DataTime類的實例,表示過時的絕對時間。

SetLastModified

用於設置頁面的Last-Modified HTTP標頭。Last-Modified HTTP標頭表示頁面上次修改時間,緩存將依靠它來進行計時。若是違反了緩存限制層次結構,此方法將失敗。該方法的參數是一個DataTime類的實例。

SetSlidingExpiration 

該方法將緩存過時從絕對時間設置爲可調時間。其參數是一個布爾值。當參數爲true時,Cache-Control HTTP標頭將隨每一個響應而更新。當參數爲false時,將保留該設置,且任何啓用可調整過時的嘗試都將靜態失敗。此方法不直接映射到HTTP標頭,它由後續模塊或輔助請求來設置源服務器緩存策略。

SetCacheability

用於設置頁面的Cache-Control HTTP標頭。該標頭用於控制在網絡上緩存文檔的方式。該方法有兩種重載方式,所不一樣的是參數。一種重載方法的參數是HttpCacheability枚舉值,包括NoCache、Private、Public、Server、ServerAndNoCache和ServerAndPrivate。另外一種方法的參數有兩個,一個參數是HttpCacheability枚舉值,另外一個參數是字符串,表示添加到標頭的緩存控制擴展。須要注意的是,僅當與Private或NoCache指令一塊兒使用時,字段擴展名纔有效。若是組合不兼容的指令和擴展,則此方法將引起無效參數異常。

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60));

Response.Cache.SetExpires(DateTime.Parse("6:00:00PM"));

Response類的Cache屬性用於獲取頁面緩存策略。該屬性的數據類型是HttpCachePolicy。可經過調用Response.Cache來獲取HttpCachePolicy實例,進而實現對於當前頁面輸出緩存的設置。如上代碼所示,第一行代碼表示輸出緩存時間是60秒,而且頁面不隨任何GET或POST參數改變,等同於「<%@ OutputCache Duration="60" VaryByParam="none" %>」。第二行代碼設置緩存過時的絕對時間是當日下午6時整。

4、頁面部分緩存

有時緩存整個頁面是不現實的,由於頁的某些部分可能在每次請求時都須要變化。在這些狀況下,只能緩存頁的一部分。顧名思義,頁面部分緩存是將頁面部份內容保存在內存中以便響應用戶請求,而頁面其餘部份內容則爲動態內容。在頁面中常常存在某些部分固定不變(如導航欄,頁面右側的排行榜等信息),而其餘內容則須要根據用戶請求的不一樣動態生成。因此咱們能夠將固定部分的內容緩存在服務器內存中,以減小服務器查詢數據時間。

頁面部分緩存也稱爲控件緩存,這種方式容許將須要緩存的信息包含在一個用戶控件內。而後,將該用戶控件標記爲可緩存的,以此來緩存頁面輸出的部份內容。這種方式容許緩存頁面中的特定內容,而不緩存整個頁面。例如,若是要建立一個顯示大量動態內容(如股票信息)的頁,其中有些部分爲靜態內容(如每週總結),這時能夠將靜態部分放在用戶控件中,並容許緩存這些內容。

頁面部分緩存示例以下: 

CacheControl.ascx的頁頭代碼中添加聲明語句:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="CacheControl.ascx.cs" Inherits="CacheControl" %>

  <%@ OutputCache Duration="60" VaryByParam="none" %>

<%=DateTime.Now %>  

調用該控件的頁面代碼:

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="CacheDemo.aspx.cs"%>
<%@ Register src="CacheControl.ascx" tagname="CacheControl" tagprefix="uc" %>
<head runat="server">
    <title>CacheDemo</title>
</head>
<body>
    <form id="form1" runat="server">
    頁面的時間:<%=DateTime.Now %> <br/>
  控件的時間:<uc:CacheControl ID="CacheControl" runat="server" /><br/>
    </form>
</body> 
</html>

當刷新頁面時,「頁面的時間」每次刷新都變化,而「控件的時間」的數據倒是60秒才變化一次。說明對頁面的「局部」控件實現了緩存,而頁面其它部分不受影響。

5、 應用程序數據緩存

應用程序數據緩存提供了一種編程方式,可經過鍵/值對將任意數據存儲在內存中。使用應用程序緩存與使用應用程序狀態相似。可是,與應用程序狀態不一樣的是,應用程序數據緩存中的數據是易失的,即數據並非在整個應用程序生命週期中都存儲在內存中。應用程序數據緩存的優勢是由ASP.NET管理緩存,它會在項過時、無效,或內存不足時移除緩存中的項。還能夠配置應用程序緩存,以便在移除項時通知應用程序。

以下所示插入一個字符串進緩存:

Cache["name"]="CacheDemo";

這個存儲的字串值能夠像這樣獲得:

if (Cache["name"] != null)
{
string name = Cache["name"].ToString();
}

6、 緩存依賴

前文的幾種方式均可以實現數據緩存功能,但問題是數據有時候是在變化的。這樣用戶可能在緩存期間查詢的數據就是過時的數據,從而致使數據的不一致。那有沒有辦法在數據變化時,系統能自動更新緩存中的數據,從而讓用戶獲得實時有效的數據。

.NET已經爲咱們提供了這樣一種很是好的解決方法:SqlCacheDependency數據庫緩存依賴。下面就讓咱們看一下如何實現數據庫緩存依賴功能:

1. 配置SqlCacheDependency 

修改web.config,讓項目啓用SqlCacheDependency。

<?xml version="1.0"?>
<configuration>
    <appSettings/>
    <connectionStrings>
        <add name="strcodematic" connectionString="data source=dbserver;initial catalog=codematic;user id=sa;password=sa"  providerName="System.Data.SqlClient" />
    </connectionStrings>
    <system.web>
        <caching>
            <sqlCacheDependency enabled="true" pollTime="6000">
                <databases>
 <add name="codematic" connectionStringName="strcodematic" />
                </databases>
            </sqlCacheDependency>         
        </caching>
      <compilation debug="true">
        </compilation>     
        <authentication mode="Windows"/>    
    </system.web>
</configuration> 

注意:在<databases>節的<add name="codematic" connectionStringName="strcodematic" />中的name屬性值必須和第三步的Page_Load代碼中System.Web.Caching.SqlCacheDependency("codematic", "P_Product"); 中的第一個參數(數據庫名稱)相一致。

這裏的connectionStringName指定了在<connectionStrings>中添加的某一個鏈接字符串。name則是爲該SqlCacheDependency起的名字,這個名字將在第三步中用到。

SqlCacheDependency類會自動完成對此配置節信息的讀取,以創建和數據庫之間的聯繫。

2.啓用緩存依賴

若是要啓用SqlCacheDependency,則須要以命令行的方式執行。

aspnet_regsql.exe工具位於Windows\\Microsoft.NET\\Framework\\[版本]文件夾中。

aspnet_regsql -C "data source=.;initial catalog=codematic;user id=sa;password=123456" -ed -et -t "BookInfo"

參數-C後面的字符串是鏈接字符串(請替換成本身所須要的值),參數-t後面的字符串是數據表的名字。

 運行結果如圖所示:

命令執行後,在指定的數據庫中會多出一個AspNet_SqlCacheTablesForChangeNotification表。

要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,須要對數據庫服務器執行相關的配置。

有兩種方法配置SQLServer:

一 使用aspnet_regsql命令行工具。

二 使用SqlCacheDependencyAdmin類。(msdn看到的,沒用過

例如:

aspnet_regsql -S "server" -E -d "database" –ed

或者

aspnet_regsql -S "server" -E -d "database" -et -t "table"

若是是Sql驗證的話要把-E換成,-U (用戶名),-P (密碼)

如下是該工具的命令參數說明:

-? 顯示該工具的幫助功能;

-S 後接的參數爲數據庫服務器的名稱或者IP地址;

-U 後接的參數爲數據庫的登錄用戶名;

-P 後接的參數爲數據庫的登錄密碼;

-E 使用當前登陸用戶的 Windows 集成認證進行身份驗證;

-d 後接參數爲對哪個數據庫採用SqlCacheDependency功能;

-C 鏈接數據庫的鏈接字符串。若是您指定服務器(-S)和登陸(-U和-P,或 -E)信息,則此選項不是必需的,由於鏈接字符串已經包含這些信息;
-t 後接參數爲對哪個表採用SqlCacheDependency功能;
-ed 容許對數據庫使用SqlCacheDependency功能;
-dd 禁止對數據庫採用SqlCacheDependency功能;
-et 容許對數據表採用SqlCacheDependency功能;
-dt 禁止對數據表採用SqlCacheDependency功能;
-lt 列出當前數據庫中有哪些表已經採用sqlcachedependency功能;

3.0使用SqlCacheDependency 

在代碼中使用緩存,併爲其設置SqlCacheDependency依賴:

 

/// <summary>
/// 獲取當前應用程序指定CacheKey的Cache對象值
/// </summary>
/// <param name="CacheKey">索引鍵值</param>
/// <returns>返回緩存對象</returns>
public static object GetCache(string CacheKey)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    return objCache[CacheKey];
}
/// <summary>
/// 設置以緩存依賴的方式緩存數據
/// </summary>
/// <param name="CacheKey">索引鍵值</param>
/// <param name="objObject">緩存對象</param>
/// <param name="cacheDepen">依賴對象</param>
public static void SetCache(string CacheKey, object objObject, System.Web.Caching.CacheDependency dep)
{
    System.Web.Caching.Cache objCache = HttpRuntime.Cache;
    objCache.Insert(
        CacheKey,
        objObject,
        dep,
        System.Web.Caching.Cache.NoAbsoluteExpiration,//從不過時
        System.Web.Caching.Cache.NoSlidingExpiration,//禁用可調過時
        System.Web.Caching.CacheItemPriority.Default,
        null);
}
protected void Page_Load(object sender, EventArgs e)
{
    string CacheKey = "cachetest";
    object objModel = GetCache(CacheKey);//從緩存中獲取
    if (objModel == null)//緩存裏沒有
    {
        objModel = GetData();//把當前時間進行緩存
        if (objModel != null)
        {
            //依賴數據庫codematic中的P_Product表變化 來更新緩存
            System.Web.Caching.SqlCacheDependency dep = new System.Web.Caching.SqlCacheDependency("CodeMatic", "P_Product");
            SetCache(CacheKey, objModel, dep);//寫入緩存
        }
    } 
    GridView1.DataSource = (DataSet)objModel;
    GridView1.DataBind();
}

從以上代碼能夠看出,和文件依賴基本相同,只是在存放緩存SetCache時存入的依賴對象不一樣。這裏用的是SqlCacheDependency。

其中,建立SqlCacheDependency的構造方法:

public SqlCacheDependency (string databaseEntryName,string tableName)
//databaseEntryName:是在Web.config文件的caching節的sqlCacheDependency的databases元素中定義的數據庫的名稱。 
//tableName:與SqlCacheDependency關聯的數據庫表的名稱。
//這樣,只有當P_Product表的內容發生變化時,查詢操做纔會從新查詢數據更新緩存的內容,能夠大大減小數據庫的重複查詢和提升系統的性能和運行效率。

7、緩存管理類

首先,緩存管理類外部代碼定義了各類過時時間的常量,主要用於方便設定緩存的過時時間

/// <summary>
    /// 全站緩存類
    /// </summary>
    public sealed class SiteCache
    {
        // 一天
        public const int DayFactor = 17280;
        // 一小時
        public const int HourFactor = 720;
        // 一分鐘
        public const int MinuteFactor = 12; 
        // 一秒
        public const double SecondFactor = 0.2;

        private static int factor = 5;
        /// <summary>
        /// 時間因子
        /// </summary>
        public static int Factor
        {
            get { return factor; }
            set { factor = value; }
        }

 public static Cache CurrentCache {
            get {
                return HttpRuntime.Cache;
            }
        }
        }
//Clear方法用於移除全部存儲在內存當中的緩存,代碼中cacheEnum變量經過GetEnumerator方法得到全部緩存列表,再根據緩存列表來移除緩存。
        public static void Clear()
        {
            //獲取緩存中的鍵設置及其值的字典枚舉數
            IDictionaryEnumerator cacheEnum = siteCache.GetEnumerator();
            ArrayList al = new ArrayList();
            //循環添加到數組列表
            while (cacheEnum.MoveNext())
            {
                al.Add(cacheEnum.Key);
            }
            //循環從緩存中移除
            foreach (string key in al)
            {
                siteCache.Remove(key);
            }
        }
//RemoveByPattern方法是經過正則移除對應的緩存。
 public static void RemoveByPattern(string pattern)
        {
            IDictionaryEnumerator cacheEnum = siteCache.GetEnumerator();
            Regex regex = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
            ArrayList al = new ArrayList();
            //循環從緩存中取出鍵進行正則條件匹配
            while (cacheEnum.MoveNext())
            {
                //匹配正確則添加到數組列表
                if (regex.IsMatch(cacheEnum.Key.ToString()))
                {
                    al.Add(cacheEnum.Key);
                }
            }
            //移除匹配正則的緩存
            foreach (string key in al)
            {
                siteCache.Remove(key);
            }
        }
//Insert方法是經過Cache的插入方法而實現的,主要可以把緩存鍵、緩存對象、緩存依賴、緩存過時時間、緩存級別這些緩存項插入到內存中。
    /// <summary>
        /// 插入緩存項
        /// </summary>
        public static void Insert(string key, object value, System.Web.Caching.CacheDependency dep, int seconds, CacheItemPriority priority)
        {
            if (value != null)
            {
                siteCache.Insert(key, value, dep, DateTime.Now.AddSeconds(Factor * seconds), TimeSpan.Zero, priority, null);
            }
        }
//Get方法經過指定的鍵從Cache中獲取緩存
        public static object Get(string key)
        {
            return siteCache[key];
        }
    }

 8、緩存的應用規則

緩存分配的有效期不要過短。
緩存那些常常被訪問,同時變化頻率不大的數據。
緩存整個應用程序都要使用的設置或對象,而且這些設置和對象在生存期內不會頻繁變化。
不要緩存太多項,緩存每一個項均有開銷。
不要緩存不多使用的項。
不要緩存容易從新計算或隨時均可能會修改的對象,如購物車。
不要緩存敏感信息,不然其餘人很容易取得這些信息。

好比:能夠緩存網站信息配置

GetConfig是一個泛型方法,網站信息配置裏的全部功能屬性都是經過它來得到對象。方法後面跟着一個where子句,用於指定對類型的約束。其中class限制了類型參數必須是引用類型, new()限制了該類型參數必須具備無參數的公共構造函數。

方法內首先獲取了T變量的類型。而後根據類型名拼裝成configCacheKey緩存鍵,經過SiteCache類的Get方法獲取緩存的值並存儲到configObject變量中。接着判斷該緩存是否不存在值,若是不存在,使用GetConfigPath方法得到了T變量的物理文件地址。

public static T GetConfig<T>() where T : class, new()
{
     Type configClassType = typeof(T);
     string configCacheKey = "CK_SiteConfigCode_" + configClassType.Name;
     object configObject = SiteCache.Get(configCacheKey);
     if (configObject == null)
     {
          string configFilePath = GetConfigPath<T>();
//下面檢查T變量的物理文件地址是否存在,若是存在即讀取T變量的配置信息,並將信息插入到緩存中。其中Insert方法使用了緩存依賴CacheDependency實例監視文件或目錄路徑,當該資源更改時,緩存的對象將過期,從緩存中移除。
          if (File.Exists(configFilePath))
          {
              using (XmlTextReader xmlTextReader = new XmlTextReader(configFilePath))
              {
                   XmlSerializer xmlSerializer = new XmlSerializer(configClassType);
                   configObject = xmlSerializer.Deserialize(xmlTextReader);
              }
              SiteCache.Insert(configCacheKey, configObject, new CacheDependency(configFilePath)); 
          }
     }
//最後,把緩存對象轉換爲T泛型變量。判斷是否爲空,若是是則建立新的T實例返回,不然將原有值返回。
     T config = configObject as T;
     if (config == null)
     {
         return new T();
     }
     else
     {
         return config;
     }
}
 
相關文章
相關標籤/搜索