DataSource Control 之Cache機制

摘要: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設為TrueCacheExpirationPolicy設為AbsoluteCacheDuration設為60DropDownList控件的DataSourceIDSqlDataSource1DataTextFieldDataValueField皆為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、一個LabelSqlDataSource控件連結至NorthwindCustomers資料表,EnableCachingTrueCacheDuration50CacheExpirationPolicyAbsoluteCacheDependencyKey屬性設為CustomersTableDropDownList控件連結至SqlDataSource控件,DataTextFieldDataValueField皆為CustomerID。此程式一開始的Page_Load函式時,先判斷是否處於PostBack模式,只有在非PostBack模式時,此範例才有執行DataBind的需求,此處先行判斷CustoemrsTable是否已經存在Cache中,是的話就代表資料物件已經在Cache中了,否的話就於Cache中插入CustomersTable,接下來的DataBind動作會是由資料庫中選取資料,然後以CustomersTable作為CacheDependency來管理資料是否過期,當IsPostBackFalse,而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

 

  SqlDataSourceAccessDataSourceObjectDataSource都支援另一個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 ControlSqlDependency中,connectionStringName參考至上方的connectionStrings區段中的設定,此處是以NorthwindConnectionString的連線字串來連結至SQL Server,然後以pollTime12000,也就是每12秒偵測一次來決定資料物件是否過期。設定完畢後,便可建立一個新網頁,如同前例般放入ButtonSqlDataSourceLabelDropDownList等控件並照前例的方式設定她們(不要設定CacheKeyDependency屬性,將CacheDuration設為300CacheExpirationPolicy設為Absolute),此處請設定SqlDataSource控件的SqlDependencyNorthwind:Customers,這個字串代表著偵測Northwind資料庫(對應web.configdatabases中的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 ControlCache機制及SqlDataSource的編輯資料能力,現在讀者們心中應會升起兩個疑問,第一個是DataSource ControlCache視界問題,當一個網站中有兩個網頁,每個網頁中都有一個SqlDataSource控件,用同樣的SQL指令至同一個資料庫中選取資料,而Cache已經啟用,此時 Cache中會有一份資料物件還是兩份呢?答案是一份,因為DataSource Control會依據連線字串、SQL指令來運算出一個鍵值,再用這個鍵值將資料物件存入Cache中,同樣的連線字串及SQL指令所運算出的鍵值是相同的。第二個問題是,當對DataSource Control下達更新動作,如InsertUpdate等等,此時Cache中的資料物件必須移除,重新選取最新的資料,而這個動作是要設計師去做,還是DataSource Control?答案是DataSource Control,當InsertUdpate等函式被呼叫時,DataSource Control便會移除Cache中的資料物件,當下次Select被呼叫時,就會重新由資料庫中選取資料。