天天看點

ASP.NET 緩存(10)

資料庫緩存依賴

資料庫緩存依賴,在資料庫中的資料更改的時候,它能自動的使緩存中的資料失效。這個特征僅在SQL 2005以及以後的版本中适用。

為了了解SQL 緩存依賴的工作原理,先了解一些過去常用的有缺陷的解決方案。

一個常用的技術是使用标記檔案。使用這種技術,你在緩存裡增加一個資料對象,然後建立起一個檔案依賴。然而,這個檔案是空檔案,你隻是用來做标記。 

當使用者調用存儲過程改變表裡的資料,存儲過程會删除或者修改标記檔案。ASP.NET會立即偵測到這個改變,然後去除符合的緩存項。這個醜陋的工作環境沒有伸縮性,并且多個存儲過程一起調用的時候,可能會有并發問題。這也迫使你存儲過程代碼混亂,因為每個存儲過程要有相似的檔案修改邏輯。讓資料庫系統和檔案系統互動是一個壞主意,增加複雜度減少安全性。

另一個常用的方法是使用自定義的http handler。在這種情況下,代替互動檔案,這些存儲過程調用http handler并且船體query string來訓示資料被改動。http handler能夠使用Cache.Remove來去除資料。

使用這種方法的問題在于,它對存儲過程的擴充有相當大的複雜性,而且,http handler請求必須是同步的,這就導緻明顯延遲。更糟的是,延遲在每次存儲過程執行時出現。

是以,我們需要的是一個可以異步通知的方法,并且是可伸縮可靠的。也就是說,資料庫伺服器應該通知ASP.NET而不需要停止目前連結。重要的是,它應該松耦合的建立緩存依賴,存儲過程不需要知道緩存這回事情。資料庫伺服器應該監控資料改變,通過各種方法,包括腳本,sql指令,或者批處理。即使改變不是直接由期望的存儲過程引發,這個改變也要被通知到ASP.NET.最終,這個通知方法要能支援web farm。

微軟把ASP.net,SQL Server, ADO.NET,IIS開發組中的架構師集中起來,一起實作一個解決方案。他們提出2種不同的架構,一種是關于SQL Server 2000 。另一種是SQL Server 2000後續版本。比如SQL Server 2005.他們都用到了SqlCacheDependency 類,該類從CacheDependency 繼承。

使用SQL緩存依賴,相對于基于時間的過期政策來說還是非常複雜。如果對實時性要求不是很高,不需要使用它。

緩存通知的工作原理

SQL Server 2005将通知架構和消息系統内建在資料庫中,叫做Service Broker。Service Broker管理隊列,這個隊列和表,存儲過程或者試圖有相同的地位。

使用Service Broker,你能夠從特定的資料庫事件中獲得通知,最直接的方法是使用CREATE EVENT NOTIFICATION 指令來訓示你要監控的事件。但是,.NET提供了一個更進階的模型,和ADO.net整合在一起。使用這個模型,你可以很簡單的注冊一個查詢指令,.NET也會自動指導SQL伺服器發送通知。ASP.NET在這個基礎上提供一個更進階别的模型,允許你在一個查詢無效的時候自動的使cache項無效。

SQL Server通知機制工作起來和索引視圖類似。每次執行一個操作,SQL Server決定該操作是否影響了注冊的指令,如果是,會發送一個通知消息,并且停止通知程序。

如下圖所示:

<a href="http://cnn237111.blog.51cto.com/attachment/201106/15/2359144_1308134447dyfF.png"></a>

啟用通知

僅有的配置就是确定你設定了資料庫的ENABLE_BROKER标志 

Use Northwind 

ALTER DATABASE Northwind SET ENABLE_BROKER

通知由Select和存儲過程一起工作。然而,使用select文法時有一些限制,你必須遵守:

必須使用表的全名,[Owner].table

不能使用聚集函數,比如count(),MAX()

不能用通配符*來選擇所有列。隻能寫成每個列名。

這些是最重要的規則,聯機幫助上還有更多的警告和說明。

建立緩存依賴

當建立緩存依賴時,SQL server需要知道你用來擷取資料的資料庫指令。如果你使用程式設計的緩存,你必須建立SqlCacheDependency對象,使用構造器來接受一個SqlCommand對象。 

// Create the ADO.NET objects. 

string connectionString = WebConfigurationManager.ConnectionStrings["Northwind"].ConnectionString; 

SqlConnection con = new SqlConnection(connectionString); 

string query ="SELECT EmployeeID, FirstName, LastName, City FROM dbo.Employees"; 

SqlCommand cmd = new SqlCommand(query, con); 

SqlDataAdapter adapter = new SqlDataAdapter(cmd); 

// Fill the DataSet. 

DataSet ds = new DataSet(); 

adapter.Fill(ds, "Employees"); 

// Create the dependency. 

SqlCacheDependency empDependency = new SqlCacheDependency(cmd); 

// Add a cache item that will be invalidated if one of its records changes 

// (or a new record is added in the same range). 

Cache.Insert("Employees", ds, empDependency); 

你也需要調用靜态方法SqlDependency.Start() 來初始化監聽Web伺服器的服務。這隻需要對每個資料庫連接配接執行一次,通常調用的地方是在global.asax檔案中的Application_Start() 方法中。

SqlDependency.Start(connectionString);

這個方法打開一個新的,非池化的資料庫連接配接。ASP.NET使用這個連接配接檢查通知隊列。初次調用Start(), 生成一個有着獨一無二名字的新的隊列會自動,新的通知服務也随即生成,然觸發一個後監聽開始。當通知收到,Web Services把通知放入隊列,SqlDependency.OnChange事件,是緩存項無效。

即使你有在幾個不同的表上有依賴,他們使用的還是相同的隊列。這意味着你隻需要調用SqlDependency.Start()。如果你不小心調用SqlDependency.Start()方法多次,不會有任何事發生。最後,你可以使用下面的代碼分離監聽。

SqlDependency.Stop(connectionString); 

通常,在Application_End() 方法中分離監聽,釋放資源。

本文轉自cnn23711151CTO部落格,原文連結:http://blog.51cto.com/cnn237111/589395 ,如需轉載請自行聯系原作者