ASP.NET的快取依賴機制-SQL快取依賴篇

iDotNetSpace發表於2009-11-05

高效使用使用SQL快取依賴
 
ASP.NET Framework新增的一個非常強大的功能是SQL快取依賴。該功能允許底層資料庫中的資料修改時,自動地重新載入快取的資料。

在使用絕對快取過期策略或者彈性快取過期策略時有一個權衡,對於效能和陳舊資料的權衡。例如,如果在記憶體中快取資料20秒,則這20秒內顯示的資料可能是過期的。

對於大多數應用程式來說,就算顯示過期資料也沒什麼關係。例如,如果我們構建一個論壇討論區,則每個使用者都能接受新的主題可能不是實時顯示的。

然而,某些型別的應用程式則絕對不能有陳舊資料。例如,如果我們建立一個股票交易網站或者拍賣網站,那麼每一秒的資料都很關鍵。

ASP.NET Framework支援的SQL快取依賴使得使用快取時可以充分利用快取,並且最小化陳舊資料。當使用SQL快取依賴時,可以自動監測底層資料庫中的資料是否變更,並重新整理快取中的資料。

ASP.NET Framework支援兩種型別的SQL快取依賴:輪詢和推。可以對任何最近版本的Microsoft SQL Server,包括Microsoft SQL Server 2005 Express、Microsoft SQL Server 2000和Microsoft SQL Server 7.0,使用輪詢SQL快取依賴。第二種型別的快取依賴——推SQL快取依賴則只能用於Microsoft SQL Server 2005和Microsoft SQL Server 2005 Express,因為它依賴SQL Server 2005 Service Broker。

可以對頁面輸出快取、資料來源控制元件快取和資料快取使用任意型別的SQL快取依賴。接下來將依次討論每一種場景。

4.6.1 使用輪詢SQL快取依賴

輪詢SQL快取依賴是最靈活的SQL快取依賴型別,所以對大多數應用程式來說,推薦使用輪詢SQL快取依賴。可以使用輪詢SQL快取依賴來檢測資料庫表的修改。

實質上,輪詢SQL快取依賴使用資料庫觸發器。當表被修改時,觸發器被觸發,名為AspNet_ SqlCacheTablesForChangeNotification的資料庫表的一行資料將被更新,用來記錄表被修改的情況。

ASP.NET Framework使用一個後臺執行緒,用來定期輪詢資料庫表的修改資訊。如果有修改,則依賴於資料庫表的快取專案從快取中移除。

如果使用輪詢SQL快取依賴,則可以消除大多數和資料庫的通訊消費。如果資料庫表還沒有更改, Web伺服器和資料庫伺服器之間唯一的通訊是檢查AspNet_SqlCacheTablesForChange- Notification表的修改的查詢。

因為輪詢SQL快取依賴必須輪詢資料庫的修改,使用輪詢SQL快取依賴的快取專案只有在資料修改時才會立即失效。輪詢時間間隔的大小決定了快取資料的陳舊程度,這個時間間隔可為任意需要的值。

4.6.2 配置輪詢SQL快取依賴

在使用輪詢SQL快取依賴之前,必須執行下面兩步配置。

(1) 必須對一個或多個資料庫表啟用SQL快取依賴。

(2) 必須在Web配置檔案中配置SQL快取依賴。

讓我們分別討論每一步。

1. 為輪詢SQL快取依賴配置資料庫

可以使用框架中的SqlCacheDependencyAdmin類來配置SQL Server資料庫以支援輪詢SQL快取依賴。該類包含如下方法。

l    DisableNotifications——用於禁用資料庫輪詢SQL快取依賴。移除所有用於表和儲存過程的輪詢快取依賴。

l    DisableTableForNotification——用於禁用特定的資料庫表的輪詢SQL快取依賴。

l    EnableNotifications——通過新增所有必需的資料庫物件,啟用資料庫的輪詢SQL快取依賴。

l    EnableTableForNotifications——啟用特定資料庫表的輪詢SQL快取依賴。

l    GetTablesEnabledForNotifications——用於返回所有啟用了輪詢SQL快取依賴的表。

不應該在ASP.NET頁面中使用SqlCacheDependencyAdmin類,因為呼叫該類的方法需要建立表、儲存過程和trigger。出於安全考慮,ASP.NET程式不應該被賦予這些許可權,而是應該在一個命令列工具中使用SqlCacheDependencyAdmin類。

ASP.NET Framework包括一個名為aspnet_regsql的命令列工具,可用它來配置資料庫以支援輪詢SQL快取依賴。該工具可以用於Microsoft SQL Server 7.0、Microsoft SQL Server 2000和Microsoft SQL Server 2005。遺憾的是,aspnet_regsql的命令列工具不支援本地Microsoft SQL Server 2005例項(不過我們馬上會修復該限制)。

aspnet_regsql工具存放在下面資料夾中:

c:\Windows\Microsoft.NET\Framework\v2.0.50727

註解   如果開啟Microsoft .NET Framework SDK程式組的SDK命令列提示程式,則不需要瀏覽Microsoft. NET目錄就能執行aspnet_regsql命令列工具。

執行下面的命令可啟用Pubs資料庫的SQL快取依賴:

aspnet_regsql -C "Data Source=localhost;Integrated Security=True;Initial

Catalog=Pubs" -ed

該命令將建立AspNet_SqlCacheTablesForChangeNotification資料庫表,並新增一組儲存過程到連線字串指定的資料庫。

啟用一個資料庫之後,就可以用如下命令來啟用特定表的SQL快取依賴:

aspnet_regsql -C "Data Source=localhost;Integrated Security=True;Initial

Catalog=Pubs" -et -t Titles

該命令啟用了Titles資料庫表的SQL快取依賴。它會給Titles資料庫表建立一個新的trigger,並新增一行新記錄到AspNet_SqlCacheTablesForChangeNotification表。

遺憾的是,不能使用標準的aspnet_regsql工具來啟用本地SQL Server 2005 Express資料庫例項的輪詢SQL快取依賴。此工具不允許在連線字串中使用AttachDBFileName引數。

為了解除該限制,我編寫了一個名為enableNotifications的自定義命令列工具,可以用它來處理本地SQL Express資料庫。該工具包含在隨書附帶資源中。

要使用enableNotifications工具,先開啟命令列工具,然後瀏覽包含本地SQL Express資料庫的資料夾。接著,執行需要啟用輪詢SQL快取依賴的資料庫檔案的名稱和資料表的名稱的命令。例如,下面的命令啟用了MyDatabase.mdf資料庫中的Movies資料庫:

enableNotifications "MyDatabase.mdf" "Movies"

enableNotifications工具只能處理Microsoft SQL Server Express 2005資料庫的例項。不能使用該工具處理其他版本的Microsoft SQL Server。

注意   當使用enableNotifications工具時,必須先瀏覽希望啟用輪詢SQL快取依賴的資料所在的資料夾。

2. 為輪詢SQL快取依賴配置應用程式

設定資料庫支援輪詢SQL快取依賴,必須要配置應用程式才能輪詢資料庫。可以使用Web配置檔案中的caching元素的sqlCacheDependency子元素來配置輪詢SQL快取依賴。

例如,程式碼清單4-41所示的檔案使得應用程式每5秒鐘(5 000毫秒)對AspNet_SqlCacheTables- ForChangeNotification表進行一次輪詢,觀察是否有更改。

程式碼清單4-41 Web.Config

   

      AttachDbFilename=|DataDirectory|MyDatabase.mdf;Integrated Security=True;

User Instance=True” />

   

    

        

          

            name=”MyDatabase”

            connectionStringName=”Movies” />

      

     

   

4.6.3 對頁面輸出快取使用輪詢SQL快取依賴

配置好輪詢SQL快取依賴後,就能對頁面輸出快取使用SQL依賴了。例如,程式碼清單4-42所示的頁面被輸出快取了,直到Movies資料庫表被修改,快取才失效。

程式碼清單4-42 PollingSQLOutputCache.aspx

   SqlDependency="MyDatabase:Movies" %>

/p>

   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

http://www.w3.org/1999/xhtml" >

   

Polling SQL Output Cache

   

   

  

   

   


  

   

        id="grdMovies"

       DataSourceID="srcMovies"

        Runat="server" />

  

   

        id="srcMovies"

        ConnectionString=""

        SelectCommand="SELECT Title, Director FROM Movies"

        Runat="server" />

 

   

   

程式碼清單4-42所示的頁面包含了一個帶有sqlDependency特性的指令。SqlDependency特性的值為Web配置檔案中啟用了SQL依賴的資料庫和資料庫表的名稱。

如果在瀏覽器中開啟如程式碼清單4-42所示的頁面,並且多次單擊瀏覽器的重新載入按鈕,你會注意到顯示的時間不會變,因為該頁被輸出快取了(見圖4-16)。

圖4-16 對頁面輸出快取使用輪詢SQL快取依賴

然而,當修改Movies資料庫表時,頁面快取將會自動失效(5秒鐘內)。再次單擊重新載入按鈕時,會顯示修改的資料。

如果希望讓一個頁面依賴多個資料庫表,則需要將sqlDependecy特性設定為一組用分號分隔的資料庫和資料庫表名的列表。

註解   也可以在一個使用者控制元件中使用 指令來使用輪詢SQL快取依賴。也就是說,可以使用輪詢SQL快取依賴來實現部分頁面快取。

4.6.4 對資料來源快取使用輪詢SQL快取依賴

要對SqlDataSource和ObjectDataSource控制元件使用輪詢SQL快取依賴,只需要設定sqlCache- Dependency屬性。例如,程式碼清單4-43所示的頁面快取了SqlDataSource控制元件的輸出,直到Movies資料庫表被修改,它才失效。

程式碼清單4-43 PollingSQLDataSourceCache.aspx

/p>

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    protected void srcMovies_Selecting(object sender, SqlDataSourceSelectingEventArgs e)

    {

        lblMessage.Text = "Retrieving data from database";

    }

http://www.w3.org/1999/xhtml" >

   

Polling SQL DataSource Cache

   

   

  

   

        id="lblMessage"

        EnableViewState="false"

        Runat="server" />

   


  

   

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

   

        id="srcMovies"

        ConnectionString=""

        SelectCommand="SELECT Title, Director FROM Movies"

        EnableCaching="true"

        SqlCacheDependency="MyDatabase:Movies"

        nSelecting="srcMovies_Selecting"

        Runat="server" />

  

   

   

在程式碼清單4-43中,SqlDataSource控制元件包括了EnableCaching屬性和SqlCacheDependency屬性。資料庫名和資料庫表名都分配了SqlCacheDependency屬性(資料庫名必須與配置在Web配置檔案元素中的資料庫名相對應)。

如果需要監視多個資料庫表,則要給SqlCacheDependency屬性指派一組用分號分隔的資料庫和資料庫表的名稱列表。

4.6.5 對資料快取使用輪詢SQL快取依賴

我們也可以對Cache物件使用輪詢SQL快取依賴,用SqlCacheDependency物件來代表一個輪詢SQL快取依賴。

例如,程式碼清單4-44所示的頁面建立了一個SqlCacheDependency物件,它代表Movies資料庫表。當DataTable新增到Cache物件時,DataTable就關聯到SqlCacheDependency物件。

程式碼清單4-44 PollingSQLDataCache.aspx

/p>

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    void Page_Load()

    {

        DataTable movies = (DataTable)Cache["Movies"];

        if (movies == null)

        {

            movies = GetMoviesFromDB();

            SqlCacheDependency sqlDepend = new SqlCacheDependency("MyDatabase", "Movies");

            Cache.Insert("Movies", movies, sqlDepend);

        }

        grdMovies.DataSource = movies;

        grdMovies.DataBind();

    }

    private DataTable GetMoviesFromDB()

    {

        Trace.Warn("Retrieving data from database");

        string conString = WebConfigurationManager.ConnectionStrings["Movies"].ConnectionString;

        SqlDataAdapter dad = new SqlDataAdapter("SELECT Title,Director FROM Movies", conString);

        DataTable movies = new DataTable();

        dad.Fill(movies);

        return movies;

    }

http://www.w3.org/1999/xhtml" >

   

Polling SQL Data Cache

   

   

  

   

        id="grdMovies"

        Runat="server" />

  

   

   

程式碼清單4-44中建立了SqlCacheDependency類的一個例項。一個資料庫名和表名傳遞給SqlCacheDependency類的建構函式。當DataTable新增到Cache時,該類就用作Cache.Insert()的一個引數。

註解   如果需要建立多個資料庫表的依賴,則需要建立多個SqlCacheDependency物件並用Aggregate- CacheDependency類的例項表示多個依賴。

4.6.6 使用推SQL快取依賴

在使用Microsoft SQL Server 2005時,除了輪詢SQL快取依賴,還可以使用推SQL快取依賴。Microsoft SQL Server 2005包含一個名為查詢通知的功能,它在後臺使用Microsoft SQL Server 2005的Service Broker。這個Service Broker可以在資料庫中的資料變更時自動給應用程式傳送一個訊息。

注意   可以用SQL Server Express建立兩種型別的資料庫:本地和伺服器資料庫。不應對本地資料庫使用推依賴,而是隻能對伺服器資料庫使用推依賴。
不能使用Visual Web Developer建立一個伺服器資料庫。只能使用完全功能的Visual Studio 2008或者從Microsoft MSDN網站(msdn.microsoft.com)下載Microsoft SQL Server Management Studio Express來建立伺服器資料庫。

相比於輪詢SQL快取依賴,使用推依賴的好處是ASP.NET應用程式不必定時地輪詢資料庫的修改。如果有修改,資料庫會通知應用程式。

也有不太好的一面,使用推依賴的查詢型別有諸多限制。下面是比較顯著的一些限制。

l    查詢必須使用兩部分的表名(例如,dbo.Movies而不是Movies)。

l    查詢必須包含一個顯式的列名列表(不能使用*)。

l    查詢不能引用檢視、繼承表、臨時表或表變數。

l    查詢不能引用大物件型別,如Text、NText和Image列。

l    查詢不能包含子查詢、外聯結或子聯結。

l    查詢不能使用DISTINCT、COMPUTE、COMPUTE BY或者INSERT關鍵字。

l    查詢不能使用許多聚合函式,包括AVG、COUNT(*)、MAX和MIN。

這裡只是一個不完整的查詢限制的列表。要檢視完整的列表,可以參考SQL Server 2005線上圖書或MSDN網站(msdn.microsoft.com)的“建立一個通知查詢”的主題。

例如,下面這個簡單的查詢不能工作:

SELECT * FROM Movies

該查詢不能工作有兩個原因。第一是不能使用星號(*)來代表列,第二是必須使用兩部分的表名。而下面這個查詢就能工作:

SELECT Title,Director FROM dbo.Movies

可以對推SQL快取依賴使用儲存過程。不過,每一個儲存過程中的SELECT語句必須滿足剛才列出的限制列表。

4.6.7 配置推SQL快取依賴

要啟用推SQL快取依賴,必須完成下面兩步配置。

l    必須配置資料庫啟用SQL Server 2005 Service Broker。

l    必須配置應用程式開始監聽通知。

在這一小節,你將瞭解到如何完成這兩個配置步驟。

注意   遺憾的是,當推快取依賴失敗時,不會有任何錯誤報告傳送到事件日誌。這就使得除錯變得極其困難。我建議,完成這一小節討論的配置修改後,重新啟動Web伺服器和資料庫伺服器。

1. 為推SQL快取依賴配置資料庫

在使用推SQL快取依賴之前,必須啟用Microsoft SQL Server 2005 Service Broker。可以執行下面的SQL查詢來檢查Service Broker是否已經為特定的資料庫啟用:

SELECT name, is_broker_enabled FROM sys.databases

如果Service Broker還沒有啟用,則要執行ALTER DATABASE命令來啟用它。例如,下面的SQL命令為MyMovies資料庫啟用了Service Broker:

ALTER DATABASE MyMovies SET ENABLE_BROKER

最後,ASP.NET程式必須有足夠的許可權來訂閱查詢通知。當一個ASP.NET頁面由IIS處理時,頁面在NT Authority WET WORK SERVICE賬號(對於Windows Server 2003或Vista)或者ASPNET賬號(對於其他作業系統,如Windows XP)上下文中執行。

執行下面的SQL命令能給YOURSERVER伺服器上的本地ASPNET賬號賦予需要的許可權:

GRANT SUBSCRIBE QUERY NOTIFICATIONS TO "YOURSERVER\ASPNET"

當使用Visual Web Developer的Web伺服器來請求一個ASP.NET頁面時,ASP.NET頁面在當前使用者賬號的安全上下文中執行。因此,當使用檔案系統網站時,需要對當前賬號執行SUBSCRIBE QUERY NOTIFICATIONS來授權。

註解    推SQL快取依賴並不使用SQL Server 2005的通知服務。

2. 為推SQL快取依賴配置應用程式

在應用程式可以接收到變更通知之前,必須啟用查詢通知監聽器。可以在如程式碼清單4-45所示的Global.asax檔案中啟用監聽器。

程式碼清單4-45 Global.asax

    void Application_Start(object sender, EventArgs e)

    {

        // Enable Push SQL cache dependencies

        string conString = WebConfigurationManager.ConnectionStrings

        ➥["MyMovies"].ConnectionString;

        SqlDependency.Start(conString);

    }

Application_Start事件處理程式只在應用程式剛開始執行時執行一次。在程式碼清單4-45中,SqlDependency.Start()方法使用一個指向SQL Express的MyMovies伺服器資料庫的連線字串呼叫。

注意   程式碼清單4-45中的程式碼在隨書附帶資源中的Global.asa檔案中被註釋了,這樣它就不會影響本章前面討論的所有程式碼。接下來,去掉註釋並使用示例程式碼。

4.6.8 對頁面輸出快取使用推SQL快取依賴

當快取整個ASP.NET頁面時,可以使用推SQL快取依賴。如果包含在頁面上的任何SQL命令的結果有改變,頁面就會自動從快取中刪除。

SqlCommand物件包含一個NotificationAutoEnlist屬性,該屬性預設值為true。當Notification- AutoEnlist啟用時,頁面和命令之間會自動建立一個推快取依賴。

例如,程式碼清單4-46所示的頁面包含指令,其中SqlDependency特性的值為CommandNotification。

程式碼清單4-46 PushSQLOutputCache.aspx

   SqlDependency="CommandNotification" %>

/p>

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

http://www.w3.org/1999/xhtml" >

  

Push SQL Output Cache

   

   

  

   

   


       

   

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

   

        id="srcMovies"

        ConnectionString=""

        SelectCommand="SELECT Title, Director FROM dbo.Movies"

        Runat="server" />

  

   

   

程式碼清單4-46所示的頁面包含一個SqlDataSource控制元件,可以從Movies資料庫表獲取所有記錄。注意,SqlDataSource控制元件使用了顯式列名的SQL查詢,並使用了兩部分格式表名。這些都是使用推快取依賴必需的。

程式碼清單4-46所示的頁面顯示了當前時間。如果從瀏覽器請求該頁面並重新整理頁面,時間不會變化。只有修改Movies資料表時,時間才會變。

注意   程式碼清單4-46所示的頁面連線到一個名為MyMovies的伺服器資料庫。不要對本地SQL Express資料庫使用推依賴。該頁面使用一個Movies資料庫表,建立這個表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)

注意   不能對包含指令的使用者控制元件使用推SQL快取依賴。也就是說,不能對部分頁面快取使用推SQL快取依賴。

4.6.9 對資料來源快取使用推SQL快取依賴

也可以對SqlDataSource和ObjectDataSource使用推SQL快取依賴,只需設定SqlCacheDependency屬性即可。不同於輪詢依賴,使用推依賴需要設定SqlCacheDependency屬性為CommandNotification。

例如,程式碼清單4-47所示的頁面包含了一個SqlDataSource控制元件,設定了EnableCaching和SqlDependency屬性集。

程式碼清單4-47 PushSQLDataSourceCache.aspx

/p>

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    protected void srcMovies_Selecting(object sender, SqlDataSourceSelectingEventArgs e)

    {

        lblMessage.Text = "Retrieving data from database";

    }

http://www.w3.org/1999/xhtml" >

   

Push SQL DataSource Cache

   

   

  

   

        id="lblMessage"

        EnableViewState="false"

        Runat="server" />

   


  

   

        id="grdMovies"

        DataSourceID="srcMovies"

        Runat="server" />

  

   

        id="srcMovies"

        ConnectionString=""

        SelectCommand="SELECT Title, Director FROM dbo.Movies"

        EnableCaching="true"

        SqlCacheDependency="CommandNotification"

        nSelecting="srcMovies_Selecting"

        Runat="server" />

  

   

   

在程式碼清單4-47中,SqlDataSource控制元件包括一個Selecting事件處理程式。因為該事件在資料不能從快取中獲得時觸發,所以可以用它來判斷資料從快取中返回還是從資料庫伺服器中返回(見圖4-17)。

圖4-17 對DataSource控制元件使用推SQL快取依賴

注意   程式碼清單4-47所示的頁面連線到一個名為MyMovies的伺服器資料庫。不要對本地SQL Express資料庫使用推依賴。該頁面使用一個Movies資料庫表,建立這個表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)

4.6.10 對資料快取使用推SQL快取依賴

也可以對Cache物件使用推SQL快取依賴。可以用一個SqlCacheDependency類的例項代表一個推SQL快取依賴。

例如,在程式碼清單4-48所示的Page_Load()事件處理程式中,一個DataTable新增到快取,它代表了Movies資料庫表的內容。這個DataTable顯示在一個GridView控制元件中。

程式碼清單4-48 PushSQLDataCache.aspx

/p>

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    void Page_Load()

    {

        DataTable movies = (DataTable)Cache["Movies"];

        if (movies == null)

        {

            Trace.Warn("Retrieving data from database");

           string conString = WebConfigurationManager.ConnectionStrings["MyMovies"].ConnectionString;

              SqlDataAdapter dad = new SqlDataAdapter("SELECT Title,Director FROM dbo.Movies", conString);

            SqlCacheDependency sqlDepend = new SqlCacheDependency(dad.SelectCommand);

            movies = new DataTable();

            dad.Fill(movies);

            Cache.Insert("Movies", movies, sqlDepend);

        }

        grdMovies.DataSource = movies;

        grdMovies.DataBind();

    }

http://www.w3.org/1999/xhtml" >

   

Push SQL Data Cache

   

   

  

   

        id="grdMovies"

        Runat="server" />

  

   

   

注意,SqlCacheDependency類的例項被建立了。一個SqlCommand物件被傳遞給了SqlCacheDependency類的建構函式。如果SqlCommand的結果變化了,則這個DataTable會自動從快取中刪除。

這些命令的順序很重要。必須在執行該命令之前建立SqlCacheDependency物件。如果在建立SqlCacheDependency物件之前呼叫Fill()方法,則依賴會被忽略。

注意   程式碼清單4-48所示的頁面連線到一個名為MyMovies的伺服器資料庫。不要對本地SQL Express資料庫使用推依賴。該頁面使用一個Movies資料庫表,建立這個表的SQL命令如下:

CREATE TABLE Movies

(

Id int IDENTITY NOT NULL,

Title nvarchar(100) NOT NULL,

Director nvarchar(50) NOT NULL,

EntryDate datetime NOT NULL DEFAULT GetDate()

)


原文地址:http://www.cnblogs.com/060218/archive/2009/11/05/1596374.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-618184/,如需轉載,請註明出處,否則將追究法律責任。

相關文章