摘要:DataSource Control 之Cache機制
DataSource Control 之Cache機制
文/黃忠成
將常用的資料物件放到Cache中,可以有效的提升整個網站的執行效能,當使用DataSource Control時,只要將EnableCacheing屬性設為True,此DataSource Control在資料選取後,便會將資料物件放到Cache中,視乎Cache過期條件的設定,在資料物件未過期前,接下來同樣條件的選取資料動作,便是直接從Cache中取出,而不需再至資料庫中選取資料。目前ASP.NET 2.0中內建的DataSource Control,除了SiteMapDataSource外,其它至少都支援兩種Cache條件設定,一是時間制,將資料物件是否過期的工作交由系統來控制,另一種是CacheDependency制,由CacheDependency物件來控制資料物件何時該過期,表4-5-2列出這兩種機制的設定方式及說明。
表4-5-2
過期條件 | 說明 |
時間制 | 當CacheExpirationPolicy屬性為Absolute時,透過設定CacheDuration屬性值來決定Cache的過期時間,該屬性值是以秒為單位,30代表當資料物件放到Cache中後,30秒後即會由Cache中移除,之後的選取資料動作將重新由資料庫中取出資料再放入Cache中。當CacheExpirationPolicy屬性為Sliding時,CacheDuration屬性代表著當資料物件放到Cache中後,經過多少時間無人存取,即從Cache中移除,例如將CacheDuration設為30,代表著30秒內無人存取時,資料物件即由Cache中移除,若有人存取,則將時間歸零,重新計算。 |
CacheDependency制 | 使用CacheDependency物件的方式來決定是否過期,設計師必須先放入一個CacheDependency物件至Cache中,再將其Key值設定給SqlDataSource控件的CacheKeyDependency屬性值,當SqlDataSource控件選取資料後,將資料物件放入Cache時會以此CacheDependency為過期條件,也就是說當此CacheDependency被移除、或是值被改變時,就視同資料物件已經過期。 |
時間制的特色是全權交由系統來控制,設計師並無從得知資料物件何時過期,也無法手動控制,所以大多用於不常更新、且沒有資料不同步問題的資料物件,程式4-5-4是一個使用時間制的範例,該程式放入了一個SqlDataSource控件、一個DropDownList控件及一個Button控件,SqlDataSource控件連結至Northwind資料庫的Customers資料表,並將EnableCaching設為True、CacheExpirationPolicy設為Absolute、CacheDuration設為60。DropDownList控件的DataSourceID為SqlDataSource1、DataTextField及DataValueField皆為CustomerID。
程式4-5-4
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; public partial class _Default : System.Web.UI.Page { //SqlDataSource1 //SQL = SELECT * FROM Customers //CacheExpirationPolicy = Absolute //CacheDuration = 60 //EnableCaching = True //------------------------------------ //DropDownList1 //DataSourceID = SqlDataSource1 //DataTextField = CustomerID //DataValueField = CustomerID //------------------------------------ //Button1 protected void Page_Load(object sender, EventArgs e) { } protected void Button1_Click(object sender, EventArgs e) { DropDownList1.DataBind(); } } |
此程式第一次執行時,SqlDataSource控件會由資料庫將資料取出後放到Cache中,之後按下Button1會觸發Click事件,此處重新呼叫了DropDownList控件的DataBind函式,迫使DropDownList控件重新對SqlDataSource控件要求資料,此時SqlDataSource控件便會從Cache中取出資料傳回,不再向資料庫索取資料。待設定的60秒過後,Cache中的資料物件將會被移除,此時再對SqlDataSource控件要求資料的話,就會重新由資料庫選取資料再放入Cache中。那我們該如何確認Cache機制是否正常運作了呢?很簡單,只要掛載事件到SqlDataSource控件的Selecting後,於其中下中斷點即可,當資料是由Cache取出時,Selecting事件不會被觸發,反之則會觸發。另一種Cache機制是以時間制為基礎,再搭配CacheDependency物件來管理Cache的過期時間,這種機制比單純使用時間制更為靈活,設計師可以在資料物件更新時,以程式的方式來迫使Cache的資料物件過期,程式4-5-5是一個使用CacheDependency物件的範例。
程式4-5-5
protected void Page_Load(object sender, EventArgs e) { Label1.Text = "Data is from Cache"; if (!IsPostBack) { if (Cache["CustomersTable"] == null) { Cache["CustomersTable"] = new CacheDependency(new string[0] {}); } } } protected void Button1_Click(object sender, EventArgs e) { Cache.Remove("CustomersTable"); DropDownList1.DataBind(); } protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e) { Label1.Text = "Data is from Database"; } |
這個範例中放入一個SqlDataSource控件、一個Button、一個Label,SqlDataSource控件連結至Northwind的Customers資料表,EnableCaching為True,CacheDuration為50,CacheExpirationPolicy為Absolute,CacheDependencyKey屬性設為CustomersTable。DropDownList控件連結至SqlDataSource控件,DataTextField與DataValueField皆為CustomerID。此程式一開始的Page_Load函式時,先判斷是否處於PostBack模式,只有在非PostBack模式時,此範例才有執行DataBind的需求,此處先行判斷CustoemrsTable是否已經存在Cache中,是的話就代表資料物件已經在Cache中了,否的話就於Cache中插入CustomersTable,接下來的DataBind動作會是由資料庫中選取資料,然後以CustomersTable作為CacheDependency來管理資料是否過期,當IsPostBack為False,而Cache中已有CustomersTable存在時,對SqlDataSource控件要求的資料將來自於Cache,當然!前題是CacheDuration所設定的時間還沒到。接下來的Button控件處理了Click事件,於此將Cache中的CustomersTable移除,然後呼叫DropDownList控件的DataBind函式,由於CacheDependency已經被移除了,此處的DataBind函式將會迫使SqlDataSource控件由資料庫中取得資料,此時便會觸發SqlDataSource控件的Selecting事件,於此改變Label控件的Text屬性值。執行此網頁後,第一次將會看到Label顯示資料來自資料庫,當重新刷新網頁時(不是按Button哦,是IE的重新整理),會看到資料已來自Cache,此後的50秒內不管刷新網頁幾次,資料都是來自於Cache,待50秒過後、或是按下網頁上的Button後,資料才會重新由資料庫中取出。
圖4-5-27(第一次啟動網頁、或按下Button後)
圖4-5-28(於50秒內重新刷新頁面時)
運用CacheDependency物件來控制資料物件的過期,對設計師來說是常用的手法。
SqlDependency
SqlDataSource、AccessDataSource、ObjectDataSource都支援另一個Cache機制:SqlDependency,此機制會偵測指定的資料庫中的資料表是否變動,若變動時資料物件會自動過期,原本這是屬於SQL Server 2005才有的新功能,經由ASP.NET 2.0的開發團隊的努力,現在此功能已經能運用在SQL Server 7以上版本的資料庫中了。SqlDependency看似神奇,但其實原理很簡單,就是利用資料庫的 Trigger機制,當資料表有所變動時,會觸發設定的Trigger,而ASP.NET 2.0所做的不過是在資料庫中產生此Trigger,並將變動存放至指定的資料表中,而SqlDependency則定期的去檢視這個資料表,一發現有所變動後就將資料物件標示為過期。由以上的敘述可以得知幾個使用SqlDependency前所需的條件,一、資料庫必須建立用來儲存變動資訊的資料表,二、資料表必須掛載偵測變動的Trigger,這兩個步驟都可透過aspnet_regsql.exe來完成,請開啟Visual Studio 2005 Command Prompt視窗,然後鍵入如圖4-5-29的命令。
圖4-5-29
第一個命令是建立儲存變動資訊的資料表,此處-S後面接的是SQL Server的名稱、-U接的是登入時的使用者名稱、-d接的是要建立資料表的資料庫、-ed代表於此建立儲存變動資訊的資料表。第二個命令是建立偵測變動的Trigger,-et代表欲建立偵測變動的Trigger,-t後面接著是要偵測的資料表名稱,完成後可以於SQL Server中看到如圖4-5-30的畫面。
圖4-5-30
在使用SqlDependency之前,得在web.config中添加程式4-5-6的設定,告知要偵測的資料庫及連線字串、偵測的時間週期。
程式4-5-6
<?xml version="1.0"?> <configuration> <appSettings/> <connectionStrings> <add name="NorthwindConnectionString" connectionString="Data Source=JEFFRAY\SQL2005;Initial Catalog=Northwind;User ID=sa" providerName="System.Data.SqlClient"/> </connectionStrings> <system.web> <caching> <sqlCacheDependency enabled="true"> <databases> <add name="Northwind" connectionStringName="NorthwindConnectionString" pollTime="12000" /> </databases> </sqlCacheDependency> </caching> |
請注意databases區段的add Tag中的資訊,name代表要偵測的資料庫別名,這待會要設定在DataSource Control的SqlDependency中,connectionStringName參考至上方的connectionStrings區段中的設定,此處是以NorthwindConnectionString的連線字串來連結至SQL Server,然後以pollTime:12000,也就是每12秒偵測一次來決定資料物件是否過期。設定完畢後,便可建立一個新網頁,如同前例般放入Button、SqlDataSource、Label、DropDownList等控件並照前例的方式設定她們(不要設定CacheKeyDependency屬性,將CacheDuration設為300、CacheExpirationPolicy設為Absolute),此處請設定SqlDataSource控件的SqlDependency為Northwind:Customers,這個字串代表著偵測Northwind資料庫(對應web.config中databases中的name)中的Customers資料表的變動,來決定資料物件是否過期,當欲偵測多個資料表時,可採;分格,例如:Northwind:Customers;Northwind:Employees、當需偵測不同資料庫的不同資料表時,也是同樣的方式:Northwind:Customers;AdvanceNorthwind:Employees。程式4-5-7為使用SqlDependency的範例。
程式4-5-7
public partial class UsingSqlDependency : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { Label1.Text = "Data is From Cache"; } protected void SqlDataSource1_Selecting(object sender, SqlDataSourceSelectingEventArgs e) { Label1.Text = "Data is From Database"; } } |
當第一次執行時,網頁會顯示資料來自資料庫,當第二次執行時,若CacheDuration所設的時間未過期,那麼將顯示資料來自Cache,當資料表有所變動時,視修改的時間而定,最慢在12秒後刷新網頁將會得到資料來自於資料庫的訊息。
再論Cache
前面已經談過DataSource Control的Cache機制及SqlDataSource的編輯資料能力,現在讀者們心中應會升起兩個疑問,第一個是DataSource Control的Cache視界問題,當一個網站中有兩個網頁,每個網頁中都有一個SqlDataSource控件,用同樣的SQL指令至同一個資料庫中選取資料,而Cache已經啟用,此時 Cache中會有一份資料物件還是兩份呢?答案是一份,因為DataSource Control會依據連線字串、SQL指令來運算出一個鍵值,再用這個鍵值將資料物件存入Cache中,同樣的連線字串及SQL指令所運算出的鍵值是相同的。第二個問題是,當對DataSource Control下達更新動作,如Insert、Update等等,此時Cache中的資料物件必須移除,重新選取最新的資料,而這個動作是要設計師去做,還是DataSource Control?答案是DataSource Control,當Insert、Udpate等函式被呼叫時,DataSource Control便會移除Cache中的資料物件,當下次Select被呼叫時,就會重新由資料庫中選取資料。