使用 SQL 緩存依賴項
最簡單的緩存策略就是使緩存數據在一個指定的時間週期後過期。但是這個簡單的方法意味着緩存數據沒有保持與底層數據源的聯繫,從而導致過期數據長時保存或當前數據很快過期。更好的方法是使用
SqlCacheDependency 類,這樣數據一直被緩存,直到其底層數據在 SQL 數據庫中被修改。本篇教程將講解怎樣使用這個類。
Part 1
簡介
使用 ObjectDataSource 緩存數據 和在架構中緩存數據 教程中探討的緩存技術使用基於時間的有效期 , 在指定的週期過後從緩存中清除數據。該方法是平衡緩存性能與數據過時的最簡單的方法。選擇 x 秒的有效期,頁面開發者雖然只能享受到 x 秒的緩存帶來的好處,但可高枕無憂,因爲數據的過期時間最多不會超過 x 秒。當然,對於靜態數據, x 可以延長爲 web 應用程序的生命週期,如 應用程序啓動時緩存數據 教程所述。
緩存數據庫數據時,人們常常會選用基於時間的有效期,因爲其易於使用。但常常這不是個合適的方案。理想情況是:數據庫數據一直被緩存,直到底層數據在數據庫中被修改;此時才清除緩存。該方法能最大地獲得緩存帶來的性能上的好處,同時使過時數據保持的時間最短。然而,爲享受到這些好處,必須建立一套系統,該系統可以感知到底層數據庫數據發生了改變並從緩存中清除相應的條目。在 ASP.NET 2.0 以前,頁面開發者負責實現該系統。
ASP.NET 2.0 提供了 SqlCacheDependency 類 以及必要的基礎架構 , 利用它們可以在數據庫發生了變化時感知到變化 , 從而清除相應的緩存條目。有兩種技術可用於感知底層數據發生的變化:通知和輪詢。下面我們會討論通知和輪詢的不同之處,之後,我們將創建必要的基礎架構來支持輪詢,然後探討怎樣通過聲明和編程兩種方式來使用 SqlCacheDependency 類。
瞭解通知和輪詢
有兩種技術可用於感知數據庫中的數據發生的變化:通知和輪詢。使用通知時,對於某個具體查詢,如果自其上次執行以來其查詢結果已發生了改變,數據庫會自動通知 ASP.NET 運行時。使用輪詢時,數據庫服務器保存特定表最近發生更改時的信息。 ASP.NET 運行時週期性地查詢數據庫,看哪些表的數據在緩存後發生過改動。其數據改動過的那些表的相關緩存條目會被清除。
選用通知技術時,需要的建立工作比輪詢少,並且具有更細的粒度,因爲該技術在查詢級而不是在表級跟蹤變化。遺憾的是,只有在 Microsoft SQL Server 2005 的完整版,即非速成 (non-Express) 版中,才能使用通知。而對於 Microsoft SQL Server 從 7.0 到 2005 之間的所有版本 , 都可採用輪詢技術。由於這些教程使用的是 SQL Server 2005 Express 版,我們將集中探討建立和使用輪詢。有關 SQL Server 2005 的通知功能的更多資料,請參考本教程末尾的更多閱讀材料部分。
採用輪詢時 , 需配置數據庫 , 使其包含一個名爲 AspNet_SqlCacheTablesForChangeNotification 的表 , 該表有三列– tableName 、notificationCreated 和changeId 。對於那些在 web 應用程序的 SQL 緩存依賴項中可能需要用到其數據的表,該表都有一條記錄與之對應。 tableName 列指定表名,而 notificationCreated 指示將該記錄添加到表中時的日期和時間。changeId 列爲 int 類型 , 其初始值爲0 。每次修改對應的表時 , 其值遞增。
除了 AspNet_SqlCacheTablesForChangeNotification 表之外,數據庫還需要對可能出現在 SQL 緩存依賴項中的每個表包含一個觸發器。每當在 AspNet_SqlCacheTablesForChangeNotification 表中插入、更新、刪除一條記錄,或表中 changeId 值遞增時,會執行這些觸發器。
在使用一個SqlCacheDependency 對象緩存數據時 ,ASP.NET 運行時會跟蹤相應表的當前 changeId 。系統週期性地檢查數據庫,一旦發現某個 SqlCacheDependency 對象的 changeId 值不同於數據庫中的相應值,就清除該對象,因爲 changeId 值不同意味着數據被緩存後相應表又有了變化。
參考資料(附實例):
使用工具:
aspnet_regsql.exe
工具地址:C:\Windows\Microsoft.NET\Framework\v2.0.50727
先在命令地工具中通過命令:cmd進入到aspnet_regsql.exe所在目錄:cd C:\Windows\Microsoft.NET\Framework\v2.0.50727
遠程服務器:128.45.4.34
數據庫名:RMA_DWH
緩存依賴的兩個表名:RMA_R_ARTICLE_LOCAL_ATTR、RMA_R_PURCHACE_ATTR
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -ed
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -t RMA_R_ARTICLE_LOCAL_ATTR -et
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -t RMA_R_PURCHACE_ATTR -et
上面的腳本執行之後,再在代碼中配置web.config文件,如下:
1:數據庫的連接字符串
<connectionStrings>
<add name="ConnectionString" connectionString="Data Source=128.45.4.34;Initial Catalog=RMA_DWH;Persist Security Info=True;User ID=sa;Password=23WSXCDE#@;Max Pool Size = 51200;" providerName="System.Data.SqlClient"/>
</connectionStrings>
2: 緩存的配置項:
<caching>
<sqlCacheDependency enabled="true" pollTime="1000" >
<databases>
<add name="RMA_DWH" connectionStringName="ConnectionString" />
</databases>
</sqlCacheDependency>
</caching>
3:asp.net代碼的使用:
protected void Page_Load(object sender, EventArgs e)
{
string TS;
DateTime time = DateTime.Now;
bool b = false;
DataTable DT = new DataTable();
<span style="color:#ff0000;">DataTable DT_Article =(DataTable)Cache["ARTICLE"];</span>
if (DT_Article != null)
DT = DT_Article;
else
{
Common.SqlBase SB = new Common.SqlBase();
DT = SB.Query_Table("SELECT TOP 1000 * FROM dbo.RMA_V_ARTICLE");
<span style="color:#ff6666;">SqlCacheDependency productsTableDependency = new SqlCacheDependency("RMA_DWH", "RMA_R_ARTICLE_LOCAL_ATTR");
Cache.Insert("ARTICLE", DT, productsTableDependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);</span>
b = true;
}
TS = (DateTime.Now - time).TotalSeconds.ToString();
if (!b)//使用緩存
{
labState.Text = "使用緩存 " + TS + " s " + DateTime.Now;
}else
{
labState.Text = "未使用緩存 " + TS + " s " + DateTime.Now;
}
ProductsDeclarative.DataSource = DT;
ProductsDeclarative.DataBind();
}
另外如果在非web層要使用cache,可以使用:HttpRuntime.Cache,多個表關聯可以使用:
AggregateCacheDependency
部分代碼如下:
Model.User userModel = new Com.AdiRMA.Model.User();
string key = string.Format("{0}_{1}", "GetUserByUserID", user_id);
if ((Model.User)<span style="color:#ff0000;">HttpRuntime.Cache</span>[key] != null)
{
userModel = (Model.User)<span style="color:#ff0000;">HttpRuntime.Cache</span>[key];
}
else
{
<span style="color:#ff0000;">AggregateCacheDependency Dependency = new AggregateCacheDependency();
SqlCacheDependency[] dependencies = {
new SqlCacheDependency("RMA_DWH", "RMA_S_USER"),
new SqlCacheDependency("RMA_DWH", "RMA_S_DEPART"),
new SqlCacheDependency("RMA_DWH", "RMA_S_USER_DEPART")
};
Dependency.Add(dependencies);
HttpRuntime.Cache.Insert(key, userModel, Dependency, Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration);</span>
}
ASP.NET的緩存依賴機制-SQL緩存依賴篇
http://blog.itpub.net/12639172/viewspace-618184/
使用 SQL 緩存依賴項
http://msdn.microsoft.com/zh-cn/dd263032
http://msdn.microsoft.com/zh-cn/dd263037
aspnet_regsql.exe -S server -U user -P password -d database -ed
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -ed
aspnet_regsql.exe -S <i>server</i> -U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -t RMA_R_ARTICLE_LOCAL_ATTR -et
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -t RMA_R_PURCHACE_ATTR -et
SqlDependency和SqlCacheDependency緩存的用法及具體步驟
http://www.webkaka.com/tutorial/asp.net/2012/111912/
如何在ASP.NET調用Global.asax文件
http://www.veryhuo.com/a/view/9402.html
關於更多命令可以參考:
http://www.cnblogs.com/ltp/archive/2009/06/30/1514331.html
取消數據庫緩存依賴:
aspnet_regsql.exe -S 128.45.4.34 -U sa -P 23WSXCDE#@ -d RMA_DWH -dd