国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開APP
userphoto
未登錄

開通VIP,暢享免費(fèi)電子書等14項(xiàng)超值服

開通VIP
使用SQL Cache Dependencies
        當(dāng)緩存數(shù)據(jù)時(shí),基于時(shí)間周期的技術(shù)因?yàn)槠湟子眯远31徊捎?,不過(guò)又常常不那么完美。理想的狀態(tài)是這樣的:數(shù)據(jù)庫(kù)數(shù)據(jù)還是應(yīng)緩存在內(nèi)存,直到源數(shù)據(jù)(underlying data)發(fā)生改變時(shí)才從內(nèi)存清除。這樣的話可以最大化的獲取緩存帶來(lái)的性能上的好處,同時(shí)使“過(guò)時(shí)數(shù)據(jù)”(stale data)持續(xù)的時(shí)間最短。然而,為此,我們需要建立一種機(jī)制來(lái)探測(cè)數(shù)據(jù)庫(kù)數(shù)據(jù)什么時(shí)候發(fā)生了改變,并將對(duì)應(yīng)的緩存條目清除掉。

  ASP.NET 2.0提供的SqlCacheDependency class類和必要的下部基礎(chǔ)構(gòu)造(infrastructure)可以判斷數(shù)據(jù)庫(kù)什么時(shí)候發(fā)生了更改,以便將對(duì)應(yīng)的緩存條目從內(nèi)存清除掉。有2種技術(shù)可以判斷源數(shù)據(jù)在什么時(shí)候發(fā)生了改變:polling 和notification。討論完這2者之間的差別后,我們將創(chuàng)建必要的下部基礎(chǔ)構(gòu)造來(lái)支持polling,然后探討如何使用SqlCacheDependency class類

  理解Notification and Polling

  正如前面所述,有2種方法來(lái)判斷一個(gè)數(shù)據(jù)庫(kù)里的數(shù)據(jù)在什么時(shí)候修改過(guò):notification 和 polling.當(dāng)使用notification的時(shí)候,數(shù)據(jù)庫(kù)提示(alerts)ASP.NET對(duì)應(yīng)某個(gè)具體查詢的數(shù)據(jù)已經(jīng)發(fā)生了改變;于是對(duì)應(yīng)的緩存條目將被清除。使用polling的時(shí)候,數(shù)據(jù)庫(kù)服務(wù)器將包含某個(gè)表(tables)最近發(fā)生更改時(shí)的相關(guān)信息。ASP.NET周期性的對(duì)數(shù)據(jù)庫(kù)進(jìn)行檢查,看哪些表在數(shù)據(jù)被緩存以后發(fā)生過(guò)改動(dòng),若改動(dòng)過(guò),對(duì)應(yīng)的緩存條目將被清除。
 
notification是對(duì)查詢(query)而不是表(table)進(jìn)行跟蹤檢查,相對(duì)polling而言,需要采取的步驟要少些。不過(guò)遺憾的是,只有在Microsoft SQL Server 2005的完整版(也就是non-Express版本)才能使用該功能。而Microsoft SQL Server的所有版本,從7.0 到2005都可以使用polling功能,因?yàn)楸鞠盗薪坛淌褂玫氖荢QL Server 2005的Express版本,在此我們將集中探討建立和使用polling。關(guān)于SQL Server 2005的notification功能,你可以參閱本文結(jié)束部分的Further Reading。

  要使用polling,我們將設(shè)置數(shù)據(jù)庫(kù)包含一個(gè)名為AspNet_SqlCacheTablesForChangeNotification的表。該表有3列:tableName, notificationCreated, 和changeId.對(duì)于哪些在web應(yīng)用程序的SQL cache dependency里要用到的表,該表都有一條記錄與之對(duì)應(yīng)。tableName就是具體某個(gè)表的名稱;notificationCreated指明了添加記錄時(shí)的date 和 time;而列changeId的類型是int,初始值是0,每當(dāng)對(duì)應(yīng)的表發(fā)生一次改動(dòng),其值就自動(dòng)增加一次。

  除了表AspNet_SqlCacheTablesForChangeNotification外,數(shù)據(jù)庫(kù)還需要為出現(xiàn)在SQL cache dependency里的每個(gè)表包含一個(gè)觸發(fā)器(triggers),任何時(shí)候,只要表插入、更新、刪除一條記錄或在表AspNet_SqlCacheTablesForChangeNotification里的對(duì)應(yīng)的changeId值增大的情況下就會(huì)執(zhí)行觸發(fā)器。

  當(dāng)使用SqlCacheDependency對(duì)象(object)來(lái)緩存數(shù)據(jù)時(shí),ASP.NET將關(guān)注某個(gè)表的當(dāng)前(current)的changeId值,一旦發(fā)現(xiàn)當(dāng)前其值與數(shù)據(jù)庫(kù)里面的changeId值不同時(shí),就將該SqlCacheDependency對(duì)象清除。因?yàn)?,changeId不吻合就意味著在完成數(shù)據(jù)緩存后,表又發(fā)生過(guò)改動(dòng)。

  第一步:考察命令行程序aspnet_regsql.exe

  如上所述,使用polling方法時(shí),必須對(duì)數(shù)據(jù)庫(kù)進(jìn)行設(shè)置以包含這些基礎(chǔ)構(gòu)造:一個(gè)預(yù)先定義的表(AspNet_SqlCacheTablesForChangeNotification),一些存儲(chǔ)過(guò)程,以及基于在SQL cache dependencies里要用到的表的觸發(fā)器。諸如這些表、存儲(chǔ)過(guò)程、觸發(fā)器等都可以通過(guò)命令行程序aspnet_regsql.exe來(lái)創(chuàng)建,該命令位于$WINDOWS$Microsoft.NETFrameworkversion文件夾。要?jiǎng)?chuàng)建表AspNet_SqlCacheTablesForChangeNotification以及相關(guān)的存儲(chǔ)過(guò)程,可以在命令行這樣運(yùn)行:
 

/* For SQL Server authentication... */
aspnet_regsql.exe -S server -U user -P password -d database -ed
  
/* For Windows Authentication... */
aspnet_regsql.exe -S server -E -d database -ed

  注意:要運(yùn)行這些命令,必須以db_securityadmin 和 db_ddladmin的身份登錄數(shù)據(jù)庫(kù),更多詳情請(qǐng)參閱作者博客:http://scottonwriting.net/sowblog/posts/10709.aspx

  比如:在Windows身份認(rèn)證模式下,對(duì)某個(gè)數(shù)據(jù)庫(kù)服務(wù)器ScottsServer里的數(shù)據(jù)庫(kù)pubs添加基礎(chǔ)構(gòu)造時(shí),在命令行鍵入:

aspnet_regsql.exe -S ScottsServer -E -d pubs -ed

  完成了數(shù)據(jù)庫(kù)級(jí)(database-level)基礎(chǔ)構(gòu)造的添加后,我們需要添加觸發(fā)器,再次使用aspnet_regsql.exe命令,不過(guò)用-t來(lái)指定"表名"(table name),且將-ed替換為-et,如下:

/* For SQL Server authentication... */
aspnet_regsql.exe -S <i>server</i>
-U <i>user</i> -P <i>password</i> -d <i>database</i> -t <i>tableName</i> -et
  
/* For Windows Authentication... */
aspnet_regsql.exe -S <i>server</i>
-E -d <i>database</i> -t <i>tableName</i> -et

  要對(duì)ScottsServer里的表authors和titles添加觸發(fā)器,這樣做:

aspnet_regsql.exe -S ScottsServer -E -d pubs -t authors -et
aspnet_regsql.exe -S ScottsServer -E -d pubs -t titles -et

  就本文而言,我們要對(duì)表Products, Categories,和Suppliers添加觸發(fā)器,具體的命令在第三步探討。
 
第二步:在文件夾App_Data里引用一個(gè)Microsoft SQL Server 2005 Express版的數(shù)據(jù)庫(kù)

  我們剛剛說(shuō)過(guò),為了添加必要的基礎(chǔ)構(gòu)造,aspnet_regsql.exe命令需要用到數(shù)據(jù)庫(kù)和服務(wù)器的名稱。但是對(duì)于放在文件夾App_Data里的一個(gè)Microsoft SQL Server 2005 Express的數(shù)據(jù)庫(kù)而言,它的數(shù)據(jù)庫(kù)名和服務(wù)器名又是什么呢?犯不著探究其數(shù)據(jù)庫(kù)名和服務(wù)器名到底是什么,我發(fā)現(xiàn)最簡(jiǎn)單的方法是用SQL服務(wù)管理器(SQL Server Management Studio)來(lái)將該數(shù)據(jù)庫(kù)認(rèn)作localhostSQLExpress database數(shù)據(jù)庫(kù),并重新命名。如果你的機(jī)器里已經(jīng)安裝了SQL Server 2005完整版,自然也就安裝了SQL服務(wù)管理器。如果你安裝的是Express版本的話,你可以免費(fèi)下載Microsoft SQL Server Management Studio Express Edition.

  (http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=C243A5AE-4BD1-4E3D-94B8-5A0F62BF7796)

  首先,關(guān)閉Visual Studio,然后打開SQL Server Management Studio,在Windows Authentication模式里選擇連接到localhostSQLExpress.

  

  圖1:連接到localhostSQLExpress Server

  連接到服務(wù)器后,管理器將顯示服務(wù)器,并將數(shù)據(jù)庫(kù)、安全等以折疊的形式顯示出來(lái)。在數(shù)據(jù)庫(kù)文件夾上右擊,選添加(Attach)項(xiàng),這樣將彈出Attach Databases對(duì)話框(見圖2),點(diǎn)Add按鈕,選擇我們的web應(yīng)用程序的App_Data文件夾里的NORTHWND.MDF數(shù)據(jù)庫(kù)。

  
 
圖2:選App_Data文件夾里的NORTHWND.MDF數(shù)據(jù)庫(kù)

  這樣將會(huì)把數(shù)據(jù)庫(kù)添加到Databases文件夾,且數(shù)據(jù)庫(kù)的名稱可能是該數(shù)據(jù)庫(kù)文件的絕對(duì)路徑(full path).出于簡(jiǎn)便的原則,我們將其重命名為一個(gè)更友好(human-friendly)的名字,我將其命名為“DataTutorials”.

  

  圖3:將新添加的數(shù)據(jù)庫(kù)重命名

  第三步:對(duì)Northwind數(shù)據(jù)庫(kù)添加Polling基礎(chǔ)構(gòu)造

  現(xiàn)在我們添加了App_Data文件夾里的NORTHWND.MDF數(shù)據(jù)庫(kù),讓我們添加polling 基礎(chǔ)構(gòu)造吧,假定你已經(jīng)將數(shù)據(jù)庫(kù)重命名為“DataTutorials”, 運(yùn)行如下的命令:

aspnet_regsql.exe -S localhostSQLExpress -E -d DataTutorials -ed
aspnet_regsql.exe -S localhostSQLExpress -E -d DataTutorials -t Products -et
aspnet_regsql.exe -S localhostSQLExpress -E -d DataTutorials -t Categories -et
aspnet_regsql.exe -S localhostSQLExpress -E -d DataTutorials -t Suppliers -et

  完成上述4個(gè)命令后,在Management Studio里右擊數(shù)據(jù)庫(kù),進(jìn)入任務(wù)子菜單(Tasks submenu),選分派(Detach)。然后關(guān)閉Management Studio并重新打開Visual Studio.

  打開Visual Studio后,在服務(wù)器資源管理器里展開數(shù)據(jù)庫(kù),你可以看到有新增的表(AspNet_SqlCacheTablesForChangeNotification),新的存儲(chǔ)過(guò)程,以及對(duì)應(yīng)于表Products, Categories, 和Suppliers的觸發(fā)器.

  
 
圖4:數(shù)據(jù)庫(kù)包含了必需的Polling基礎(chǔ)構(gòu)造

  第四步:設(shè)置Polling服務(wù)

  完成上述步驟后,最后我們需要設(shè)置polling服務(wù)。這要用到Web.config文件,在里面指定要用到的數(shù)據(jù)庫(kù),以及檢測(cè)頻率(polling frequency),單位為毫秒。下面的代碼是每隔1秒對(duì)Northwind數(shù)據(jù)庫(kù)檢測(cè)一次。

<?xml version="1.0"?>
<configuration>
  <connectionStrings>
   <add name="NORTHWNDConnectionString" connectionString=
     "Data Source=.SQLEXPRESS;AttachDbFilename=|DataDirectory|NORTHWND.MDF;
      Integrated Security=True;User Instance=True"
      providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.web>
   ...
  
   <!-- Configure the polling service used for SQL cache dependencies -->
   <caching>
     <sqlCacheDependency enabled="true" pollTime="1000" >
      <databases>
        <add name="NorthwindDB"
          connectionStringName="NORTHWNDConnectionString" />
      </databases>
     </sqlCacheDependency>
   </caching>
  </system.web>
</configuration>

  在<add>元素里的name值(“NorthwindDB”)是一個(gè)易讀(human-readable)的名稱,它與某個(gè)具體的數(shù)據(jù)庫(kù)對(duì)應(yīng)。當(dāng)使用SQL cache dependencies的時(shí)候,我們需要引用在這里定義的數(shù)據(jù)庫(kù)名。我們將在第六步考察怎樣使用SqlCacheDependency class類來(lái)緩存數(shù)據(jù)。
 
一旦確定了一個(gè)SQL cache dependency后,檢測(cè)系統(tǒng)(polling system)每隔定義的pollTime那么多毫秒對(duì)<databases>元素里的數(shù)據(jù)庫(kù)進(jìn)行連接,并執(zhí)行名為AspNet_SqlCachePollingStoredProcedure的存儲(chǔ)過(guò)——該存儲(chǔ)過(guò)程是我們?cè)诘谌绞褂胊spnet_regsql.exe命令行工具添加的,它返回的是表AspNet_SqlCacheTablesForChangeNotification里的每條記錄的tableName 和 changeId值。那些“過(guò)時(shí)”的SQL cache dependencies將會(huì)從內(nèi)存清除掉。

  應(yīng)在權(quán)衡性能和數(shù)據(jù)刷新(data staleness)的基礎(chǔ)上設(shè)置pollTime.較小的pollTime值雖然導(dǎo)致請(qǐng)求數(shù)據(jù)庫(kù)的次數(shù)增加,但能更快的將“過(guò)時(shí)"的數(shù)據(jù)清除掉;較大的pollTime值雖然減少了對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求次數(shù),但增加了“過(guò)時(shí)”的緩存條目的呆滯時(shí)間。還好,對(duì)數(shù)據(jù)庫(kù)的請(qǐng)求只是執(zhí)行一個(gè)簡(jiǎn)單的存儲(chǔ)過(guò)程而已,該存儲(chǔ)過(guò)程僅僅從一個(gè)簡(jiǎn)單的表返回很少的幾行。你最好多測(cè)試幾個(gè)不同的pollTime值,在平衡數(shù)據(jù)庫(kù)訪問(wèn)和數(shù)據(jù)刷新2方面的情況下找出一個(gè)理想的值。pollTime值最小允許為500.

  注意:在上面的代碼里,我們?cè)?lt;sqlCacheDependency>元素里指定了一個(gè)單一的pollTime值。其實(shí)你也可以在<add>元素里隨意的指定一個(gè)pollTime值。當(dāng)你指定了很多個(gè)數(shù)據(jù)庫(kù),且你想為每個(gè)數(shù)據(jù)庫(kù)都指定一個(gè)檢測(cè)頻率(polling frequency)時(shí),這樣做很有用。

  第五:聲明SQL Cache Dependencies

  在第一到第四步驟,我們探討了如何建立必需的數(shù)據(jù)庫(kù)基礎(chǔ)構(gòu)造,以及設(shè)置檢測(cè)系統(tǒng)(polling system).完成上述步驟后,現(xiàn)在我們可以通過(guò)編程或聲明的方式,在添加緩存條目時(shí)使用SQL cache dependency.在本節(jié),我們探討如何使用聲明的方式使用SQL cache dependencies,在第六步再探討通過(guò)編程的方式。
 

  在《Caching Data with the ObjectDataSource》教程里,我們考察了聲明ObjectDataSource控件的緩存功能。僅僅將EnableCaching屬性設(shè)置為true,并將acheDuration屬性設(shè)置為某個(gè)時(shí)間間(timeinterval),ObjectDataSource控件就會(huì)自動(dòng)地將從“源對(duì)象”(underlying object)返回的數(shù)據(jù)進(jìn)行緩存。ObjectDataSource控件可以使用單個(gè)或多個(gè)SQL cache dependencies.

  為此,打開文件夾Caching里的SqlCacheDependencies.aspx頁(yè)面,在設(shè)計(jì)模式里,從工具箱拖一個(gè)GridView控件到頁(yè)面上,設(shè)置其ID為ProductsDeclarative ,從其智能標(biāo)簽里將其綁定到一個(gè)名為ProductsDataSourceDeclarative的ObjectDataSource.

  

  圖5:創(chuàng)建一個(gè)名為ProductsDataSourceDeclarative的ObjectDataSource

  設(shè)置該ObjectDataSource使用ProductsBLL類。在SELECT標(biāo)簽里選GetProducts()方法;在UPDATE標(biāo)簽里,選擇包含3個(gè)輸入?yún)?shù)——productName,unitPrice,和productID的UpdateProduct重載方法;在INSERT 和 DELETE標(biāo)簽里選“(None)”.

  

  圖6:使用包含3個(gè)輸入?yún)?shù)的UpdateProduct重載方法

  
 
圖7:在INSERT和DELETE標(biāo)簽的下拉列表里選“(None)”

  完成設(shè)置后,Visual Studio會(huì)為GridView里的每一列創(chuàng)建綁定列(BoundFields) 和CheckBoxFieldsL列。將ProductName, CategoryName, 和UnitPrice以外的列都刪除,對(duì)其應(yīng)用什么格式化都可以。在GridView的智能標(biāo)簽里啟用分頁(yè)、排序、編輯功能。Visual Studio會(huì)將ObjectDataSource控件的OldValuesParameterFormatString屬性設(shè)置為original_{0},為使GridView的編輯功能運(yùn)行正常,要么刪除該屬性,要么將其設(shè)置為默認(rèn)值:{0}.

  最后,在GridView上面添加一個(gè)Label Web控件,設(shè)置其ID為ODSEvents,再將其EnableViewState屬性設(shè)置為false.做完上述修改后,頁(yè)面的聲明代碼看起來(lái)應(yīng)該和下面的差不多。注意,我已經(jīng)對(duì)GridView列的外觀做了些定制,雖然這對(duì)SQL cache dependency功能來(lái)說(shuō)并不是必要的。

<asp:Label ID="ODSEvents" runat="server" EnableViewState="False" />
  
<asp:GridView ID="ProductsDeclarative" runat="server"
  AutoGenerateColumns="False" DataKeyNames="ProductID"
  DataSourceID="ProductsDataSourceDeclarative"
  AllowPaging="True" AllowSorting="True">
  <Columns>
    <asp:CommandField ShowEditButton="True" />
    <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
      <EditItemTemplate>
        <asp:TextBox ID="ProductName" runat="server"
          Text='<%# Bind("ProductName") %>' />
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1"
          ControlToValidate="ProductName" Display="Dynamic"
          ErrorMessage="You must provide a name for the product."
          SetFocusOnError="True"
          runat="server">*</asp:RequiredFieldValidator>
      </EditItemTemplate>
      <ItemTemplate>
        <asp:Label ID="Label2" runat="server"
          Text='<%# Bind("ProductName") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:BoundField DataField="CategoryName" HeaderText="Category"
      ReadOnly="True" SortExpression="CategoryName" />
    <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
      <EditItemTemplate>
        $<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
          Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
        <asp:CompareValidator ID="CompareValidator1" runat="server"
          ControlToValidate="UnitPrice"
          ErrorMessage="You must enter a valid currency value with
            no currency symbols. Also, the value must be greater than
            or equal to zero."
          Operator="GreaterThanEqual" SetFocusOnError="True"
          Type="Currency" Display="Dynamic"
          ValueToCompare="0">*</asp:CompareValidator>
      </EditItemTemplate>
      <ItemStyle HorizontalAlign="Right" />
      <ItemTemplate>
        <asp:Label ID="Label1" runat="server"
          Text='<%# Bind("UnitPrice", "{0:c}") %>' />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>
  
<asp:ObjectDataSource ID="ProductsDataSourceDeclarative" runat="server"
  SelectMethod="GetProducts" TypeName="ProductsBLL"
  UpdateMethod="UpdateProduct">
  <UpdateParameters>
    <asp:Parameter Name="productName" Type="String" />
    <asp:Parameter Name="unitPrice" Type="Decimal" />
    <asp:Parameter Name="productID" Type="Int32" />
  </UpdateParameters>
</asp:ObjectDataSource>
 
下一步,為ObjectDataSource控件的Selecting事件創(chuàng)建一個(gè)事件處理器:

protected void ProductsDataSourceDeclarative_Selecting
  (object sender, ObjectDataSourceSelectingEventArgs e)
{
  ODSEvents.Text = "-- Selecting event fired";
}

  我們知道,只有當(dāng)ObjectDataSource控件從它的相關(guān)“源對(duì)象”(underlying object)獲取數(shù)據(jù)時(shí)才會(huì)觸發(fā)它的Selecting事件。如果ObjectDataSource是從內(nèi)存檢索數(shù)據(jù)的話,將不會(huì)觸發(fā)Selecting事件.

  現(xiàn)在,在瀏覽器里登錄該頁(yè)面,因?yàn)槲覀冞€沒有進(jìn)行緩存,所以每當(dāng)你分頁(yè)、排序、編輯時(shí),頁(yè)面都會(huì)顯示文本——“—Selecting event fired”, 如圖8所示:

  

  圖8:當(dāng)分頁(yè)、排序、編輯時(shí)都會(huì)觸發(fā)ObjectDataSource的Selecting事件。

  就像我們?cè)诮坛獭禖aching Data with the ObjectDataSource》里探討的一樣,除了EnableCaching屬性以外,ObjectDataSource控件還有SqlCacheDependency property屬性,它可以為緩存數(shù)據(jù)添加一個(gè)或更多的

  SQL cache dependencies.像下面這樣:

  databaseName1:tableName1;databaseName2:tableName2;...

  其中,databaseName是Web.config文件里<add>元素的name屬性指定的數(shù)據(jù)庫(kù)名,而tableName就是數(shù)據(jù)庫(kù)里的一個(gè)表。舉個(gè)例,要?jiǎng)?chuàng)建一個(gè)ObjectDataSource,它用SQL cache dependency來(lái)緩存數(shù)據(jù),當(dāng)我們指定要用Northwind數(shù)據(jù)庫(kù)里的 Products表時(shí),我們將ObjectDataSource的EnableCaching屬性設(shè)置為true,且SqlCacheDependency屬性為“NorthwindDB:Products”.
 
注意:你可以通過(guò)設(shè)置EnableCaching屬性為true來(lái)使用一個(gè) SQL cache dependency和基于時(shí)間的緩存期(time-based expiry)。CacheDuration對(duì)應(yīng)時(shí)間間隔;SqlCacheDependency對(duì)應(yīng)數(shù)據(jù)庫(kù)名和表名。不管是緩存到期還是檢查系統(tǒng)(polling system)發(fā)現(xiàn)“源數(shù)據(jù)”發(fā)生改變,只要其中一個(gè)發(fā)生, ObjectDataSource 都會(huì)將清除其數(shù)據(jù)。

  在SqlCacheDependencies.aspx頁(yè)面里的GridView 控件從2個(gè)表獲取數(shù)據(jù)——Products 和 Categories (產(chǎn)品的CategoryName列是通過(guò)語(yǔ)法 JOIN on Categories來(lái)獲取的). 因此,我們想指定2個(gè)SQL cache dependencies:

  “NorthwindDB:Products;NorthwindDB:Categories”.

  

  圖9:設(shè)置ObjectDataSource支持緩存,且使用基于表Products 和 Categories的SQL Cache Dependencies

  設(shè)置SQL Cache Dependencies支持緩存后,再次來(lái)瀏覽器里登錄頁(yè)面。最開始,文本“—Selecting event fired”依然會(huì)出現(xiàn)在頁(yè)面里,但當(dāng)進(jìn)行分頁(yè)、排序或點(diǎn)擊編輯和取消按鈕時(shí),文本就消失了。這是因?yàn)閷?duì)數(shù)據(jù)進(jìn)行緩存后,其緩存狀態(tài)一直持續(xù),直到Products 或 Categories表發(fā)生了改變,或我們通過(guò)GridView對(duì)數(shù)據(jù)進(jìn)行了更新。

  做個(gè)實(shí)驗(yàn),在第一個(gè)瀏覽器窗口進(jìn)行分頁(yè)操作,請(qǐng)注意文本“—Selecting event fired”并沒有顯現(xiàn)出來(lái)。再打開第2個(gè)瀏覽器窗口,導(dǎo)航到頁(yè)面Basics.aspx頁(yè)面(~/EditInsertDelete/Basics.aspx). 對(duì)某個(gè)產(chǎn)品的name 或 price進(jìn)行更新。 再次返回到第一個(gè)瀏覽器窗口,查看下一個(gè)頁(yè)面或進(jìn)行排序操作或點(diǎn)擊某行的編輯按鈕,這一次,文本“—Selecting event fired又出現(xiàn)了,這是因此“源數(shù)據(jù)”發(fā)生了更改(見圖10)。如果文本沒有出現(xiàn),請(qǐng)稍等一下再試一回。我們知道,polling服務(wù)每隔設(shè)定的pollTime那么多毫秒對(duì)Products表進(jìn)行檢查,開是否改動(dòng)過(guò)。因此在源數(shù)據(jù)的更新和“過(guò)時(shí)”數(shù)據(jù)的清除之間有個(gè)延遲期。
 

  圖10:改動(dòng)Products表將導(dǎo)致清除“過(guò)時(shí)”的Product緩存數(shù)據(jù)

  第六步:通過(guò)編程的方式處理SqlCacheDependency類

  在教程《Caching Data in the Architecture 》我們看到了使用單獨(dú)的緩存層 Caching Layer的好處。在那篇教程,我們創(chuàng)建了一個(gè)ProductsCL 類來(lái)處理data cache.要在緩存層Caching Layer利用SQL cache dependencies的話,要用到SqlCacheDependency 類。

  在檢測(cè)系統(tǒng)(polling system)里,一個(gè)SqlCacheDependency對(duì)象必須與某個(gè)具體的數(shù)據(jù)庫(kù)和表掛鉤。下面的代碼,創(chuàng)建了一個(gè)SqlCacheDependency對(duì)象,它基于Northwind數(shù)據(jù)庫(kù)的Products表:

Caching.SqlCacheDependency productsTableDependency =
  new Caching.SqlCacheDependency("NorthwindDB", "Products");

  上面的2個(gè)參數(shù)分別對(duì)應(yīng)數(shù)據(jù)庫(kù)名和表名。與ObjectDataSource控件的屬性SqlCacheDependency類似,數(shù)據(jù)庫(kù)名是使用的Web.config.文件里<add> 元素的name屬性指定的值,而表名是實(shí)際的數(shù)據(jù)庫(kù)表名.。

  要將一個(gè)SqlCacheDependency與添加到內(nèi)存的條目聯(lián)系起來(lái),可以使用一個(gè)重載的接受dependency的Insert方法。下面代碼里的SqlCacheDependency基于表Products,且緩存時(shí)間未定。換句話說(shuō),數(shù)據(jù)會(huì)一直保存在內(nèi)存,除非內(nèi)存不足或表Products發(fā)生了改變才被清除掉。

Caching.SqlCacheDependency productsTableDependency =
  new Caching.SqlCacheDependency("NorthwindDB", "Products");
Cache.Insert(key,
       value,
       productsTableDependency,
       System.Web.Caching.Cache.NoAbsoluteExpiration,
       System.Web.Caching.Cache.NoSlidingExpiration);
 
目前,緩存層Caching Layer的ProductsCL類從表Products獲取數(shù)據(jù),緩存時(shí)間為60秒。 讓我們對(duì)其進(jìn)行更新,使其使用SQL cache dependencies. 類ProductsCL的AddCacheItem方法是用來(lái)向內(nèi)存添加數(shù)據(jù)的,其當(dāng)前代碼如下:

private void AddCacheItem(string rawKey, object value)
{
  System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
  
  // Make sure MasterCacheKeyArray[0] is in the cache
  DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
  
  // Add a CacheDependency
  Caching.CacheDependency dependency =
    new Caching.CacheDependency(null, MasterCacheKeyArray);
  DataCache.Insert(GetCacheKey(rawKey), value, dependency,
    DateTime.Now.AddSeconds(CacheDuration),
    System.Web.Caching.Cache.NoSlidingExpiration);
}

  讓我們對(duì)其進(jìn)行更新,用一個(gè)SqlCacheDependency對(duì)象來(lái)替換掉MasterCacheKeyArray cache dependency:

private void AddCacheItem(string rawKey, object value)
{
  System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
  
  // Add the SqlCacheDependency objects for Products
  Caching.SqlCacheDependency productsTableDependency =
    new Caching.SqlCacheDependency("NorthwindDB", "Products");
  
  // Add the item to the data cache using productsTableDependency
  DataCache.Insert(GetCacheKey(rawKey), value, productsTableDependency,
    Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}
 
我們來(lái)進(jìn)行測(cè)試。在名為ProductsDeclarative的GridView控件下再添加一個(gè)GridView,設(shè)置其ID為ProductsProgrammatic,在其智能標(biāo)里將其綁定到一個(gè)名為ProductsDataSourceProgrammatic的新的ObjectDataSource,設(shè)置該ObjectDataSource使用ProductsCL類,分別在SELECT 和 UPDATE標(biāo)簽里選GetProducts 和 UpdateProduct方法。

  

  圖11:設(shè)置新ObjectDataSource使用ProductsCL類

  

  圖12:在SELECT標(biāo)簽里選GetProducts方法

  

  圖13:在UPDATE標(biāo)簽選UpdateProduct方法

  完成設(shè)置后,Visual Studio會(huì)自動(dòng)地為GridView控件添加BoundFields和 CheckBoxFields。就像上面那個(gè)GridView控件一樣,將ProductName, CategoryName, 和 UnitPrice以外的列都刪除掉。在其智能標(biāo)簽里,啟用分頁(yè)、排序、編輯功能。同時(shí),為使GridView控件的編輯功能正常工作,將OldValuesParameterFormatString屬性改成默認(rèn)值{0}. 或干脆在代碼聲明里將該屬性刪除。

  完成上述修改后,最終的GridView 和 ObjectDataSource的聲明代碼看起來(lái)應(yīng)該和下面的差不多:

<asp:GridView ID="ProductsProgrammatic" runat="server"
  AutoGenerateColumns="False" DataKeyNames="ProductID"
  DataSourceID="ProductsDataSourceProgrammatic" AllowPaging="True"
  AllowSorting="True">
  <Columns>
    <asp:CommandField ShowEditButton="True" />
    <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
      <EditItemTemplate>
        <asp:TextBox ID="ProductName" runat="server"
          Text='<%# Bind("ProductName") %>' />
        <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
          ControlToValidate="ProductName" Display="Dynamic"
          ErrorMessage="You must provide a name for the product."
          SetFocusOnError="True"
          runat="server">*</asp:RequiredFieldValidator>
      </EditItemTemplate>
      <ItemTemplate>
        <asp:Label ID="Label2" runat="server"
          Text='<%# Bind("ProductName") %>' />
      </ItemTemplate>
    </asp:TemplateField>
    <asp:BoundField DataField="CategoryName" HeaderText="Category"
      ReadOnly="True" SortExpression="CategoryName" />
    <asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
      <EditItemTemplate>
        $<asp:TextBox ID="UnitPrice" runat="server" Columns="8"
          Text='<%# Bind("UnitPrice", "{0:N2}") %>'></asp:TextBox>
        <asp:CompareValidator ID="CompareValidator1" runat="server"
          ControlToValidate="UnitPrice" Display="Dynamic"
          ErrorMessage="You must enter a valid currency value with
            no currency symbols. Also, the value must be greater than
            or equal to zero."
          Operator="GreaterThanEqual" SetFocusOnError="True"
          Type="Currency" ValueToCompare="0">*</asp:CompareValidator>
      </EditItemTemplate>
      <ItemStyle HorizontalAlign="Right" />
      <ItemTemplate>
        <asp:Label ID="Label1" runat="server"
          Text='<%# Bind("UnitPrice", "{0:c}") %>' />
      </ItemTemplate>
    </asp:TemplateField>
  </Columns>
</asp:GridView>
  
<asp:ObjectDataSource ID="ProductsDataSourceProgrammatic" runat="server"
  OldValuesParameterFormatString="{0}" SelectMethod="GetProducts"
  TypeName="ProductsCL" UpdateMethod="UpdateProduct">
  <UpdateParameters>
    <asp:Parameter Name="productName" Type="String" />
    <asp:Parameter Name="unitPrice" Type="Decimal" />
    <asp:Parameter Name="productID" Type="Int32" />
  </UpdateParameters>
</asp:ObjectDataSource>
 
要測(cè)試位于緩存層的SQL cache dependency,先在ProductCL類的AddCacheItem方法里設(shè)置斷點(diǎn)(breakpoint),然后啟動(dòng)調(diào)試。當(dāng)你首次登錄SqlCacheDependencies.aspx頁(yè)面時(shí),應(yīng)該可以發(fā)生斷點(diǎn),因?yàn)槭堑谝淮握?qǐng)求數(shù)據(jù),且把數(shù)據(jù)添加到內(nèi)存。然后,在GridView里跳轉(zhuǎn)到下一頁(yè)或?qū)δ硞€(gè)列排序,這將導(dǎo)致GridView控件查詢所需的數(shù)據(jù),數(shù)據(jù)應(yīng)該還駐存在內(nèi)存因?yàn)楸鞵roducts沒有改動(dòng)過(guò)。如果一直無(wú)法在內(nèi)存找到所需的數(shù)據(jù),務(wù)必確保內(nèi)存夠大,然后再試一次。

  在GridView里多跳轉(zhuǎn)幾頁(yè),再另外打開一個(gè)瀏覽器窗口,導(dǎo)航到Basics.aspx頁(yè)面(~/EditInsertDelete/Basics.aspx). 更新一條記錄。再回到第一個(gè)瀏覽器窗口,再跳轉(zhuǎn)頁(yè)面或?qū)嵤┡判颉?/p>

  此時(shí),你會(huì)遇到下面2種情況之一:要么程序發(fā)生斷點(diǎn),提示你數(shù)據(jù)被清除了,原圖是數(shù)據(jù)庫(kù)發(fā)生了改動(dòng);要么程序沒有發(fā)生斷點(diǎn),這意味著頁(yè)面SqlCacheDependencies.aspx顯示的是“過(guò)時(shí)”的數(shù)據(jù)。如果沒有發(fā)生斷點(diǎn),很可能是當(dāng)數(shù)據(jù)改變時(shí)沒有觸發(fā)polling服務(wù)(polling service).我們知道,polling服務(wù)每隔設(shè)定的pollTime那么多毫秒對(duì)Products表進(jìn)行檢查,看是否改動(dòng)過(guò)。因此在源數(shù)據(jù)的更新和“過(guò)時(shí)”數(shù)據(jù)的清除之間有個(gè)延遲期。

  注意:延遲很可能是當(dāng)我們?cè)赟qlCacheDependencies.aspx頁(yè)面里的GridView里編輯產(chǎn)品信息時(shí)發(fā)生的。在教程《Caching Data in the Architecture》里,

  我們添加MasterCacheKeyArray cache dependency來(lái)確保數(shù)據(jù)從內(nèi)存清除。但在前面我們修改AddCacheItem方法時(shí)將其替換掉了,因此ProductsCL類將繼續(xù)顯示“過(guò)時(shí)”的數(shù)據(jù),直到檢測(cè)系統(tǒng)發(fā)現(xiàn)Products發(fā)生過(guò)改動(dòng)。我們將在第七步看如何重新引入MasterCacheKeyArray cache dependency.
 
第七步:對(duì)緩存條目附加多個(gè)Dependencies

  我們知道, MasterCacheKeyArray cache dependency的用處在于:與 product相關(guān)的所有條目中,只要其中任意一條的相關(guān)數(shù)據(jù)發(fā)生更改后,所有的條目都會(huì)被清除掉。舉個(gè)例,GetProductsByCategoryID(categoryID)方法根據(jù)指定的categoryID獲取多條產(chǎn)品記錄并緩存,只要其中任何一條記錄被清除掉的話, MasterCacheKeyArray cache dependency 會(huì)確保剩下的其它記錄也會(huì)被清除掉。

  沒有MasterCacheKeyArray cache dependency的話,就會(huì)存在這種可能性,當(dāng)某個(gè)條目更改過(guò)后,剩余的條目仍然駐留在內(nèi)存而顯得“過(guò)時(shí)”。因此,在使用SQL cache dependencies的時(shí)候包含MasterCacheKeyArray cache dependency是很重要的。然而,data cache的Insert 方法只允許存在一個(gè)dependency 對(duì)象。

  此外,當(dāng)使用SQL cache dependencies的時(shí)候,我們可能要依賴多個(gè)表。比如,ProductsCL類的ProductsDataTable里還包含了每個(gè)產(chǎn)品的種類(category)和供應(yīng)商名稱(supplier names).但是在AddCacheItem方法里,只依賴 表Products.設(shè)想,如果用戶更新了種類或供應(yīng)商,那么緩存的product數(shù)據(jù)仍然駐留在內(nèi)存,顯然已經(jīng)"過(guò)時(shí)"了。因此,我們想時(shí)緩存的product數(shù)據(jù)不僅依賴Products表,還要依賴Categories 和 Suppliers 表.

  不過(guò)類AggregateCacheDependency提供了這個(gè)途徑,將一個(gè)緩存條目與多個(gè)dependencies聯(lián)系起來(lái)。首先,創(chuàng)建一個(gè)AggregateCacheDependency實(shí)例;然后用AggregateCacheDependency的 Add 方法添加設(shè)置好的dependencies.當(dāng)AggregateCacheDependency 實(shí)例里的任何一個(gè)dependencies發(fā)生改動(dòng)以后,緩存條目就會(huì)被清除掉。

  下面的代碼是更新過(guò)的ProductsCL類的 AddCacheItem 方法。該方法不僅創(chuàng)建了MasterCacheKeyArray cache dependency,還創(chuàng)建了基于表Products, Categories,和 Suppliers的多個(gè)SqlCacheDependency objects對(duì)象。再把它們組合起來(lái)構(gòu)成一個(gè)名為aggregateDependencies的AggregateCacheDependency object 對(duì)象,將該對(duì)象傳遞給Insert方法.
 

private void AddCacheItem(string rawKey, object value)
{
  System.Web.Caching.Cache DataCache = HttpRuntime.Cache;
  
  // Make sure MasterCacheKeyArray[0] is in the cache and create a depedency
  DataCache[MasterCacheKeyArray[0]] = DateTime.Now;
  Caching.CacheDependency masterCacheKeyDependency =
    new Caching.CacheDependency(null, MasterCacheKeyArray);
  
  // Add the SqlCacheDependency objects for Products, Categories, and Suppliers
  Caching.SqlCacheDependency productsTableDependency =
    new Caching.SqlCacheDependency("NorthwindDB", "Products");
  Caching.SqlCacheDependency categoriesTableDependency =
    new Caching.SqlCacheDependency("NorthwindDB", "Categories");
  Caching.SqlCacheDependency suppliersTableDependency =
    new Caching.SqlCacheDependency("NorthwindDB", "Suppliers");
  
  // Create an AggregateCacheDependency
  Caching.AggregateCacheDependency aggregateDependencies =
    new Caching.AggregateCacheDependency();
  aggregateDependencies.Add(masterCacheKeyDependency, productsTableDependency,
    categoriesTableDependency, suppliersTableDependency);
  
  DataCache.Insert(GetCacheKey(rawKey), value, aggregateDependencies,
    Caching.Cache.NoAbsoluteExpiration, Caching.Cache.NoSlidingExpiration);
}

 

  對(duì)代碼進(jìn)行測(cè)試?,F(xiàn)在,更改表Products、 Categories, 或Suppliers的話將清除掉緩存數(shù)據(jù)。另外,當(dāng)在GridView控件里編輯某個(gè)產(chǎn)品的話將調(diào)用ProductsCL 類的 UpdateProduct方法,該方法清除掉 MasterCacheKeyArray cache dependency,進(jìn)而導(dǎo)致連鎖反應(yīng)清除掉緩存的ProductsDataTable.最后的結(jié)果是,當(dāng)下次請(qǐng)求數(shù)據(jù)時(shí)將重新從數(shù)據(jù)庫(kù)檢索數(shù)據(jù)。

  注意:也可以通過(guò)output caching來(lái)使用SQL cache dependencies.欲見詳情,請(qǐng)參考《Using ASP.NET Output Caching with SQL Server.》(http://msdn2.microsoft.com/en-us/library/e3w8402y(VS.80).aspx)

  結(jié)語(yǔ):

  當(dāng)緩存數(shù)據(jù)庫(kù)數(shù)據(jù)時(shí),最理想的狀態(tài)是數(shù)據(jù)一直駐留在內(nèi)存,直到數(shù)據(jù)庫(kù)發(fā)生了改動(dòng)。在ASP.NET 2.0,可以通過(guò)編程或聲明代碼的方式使用SQL cache dependencies ,該方法面臨的挑戰(zhàn)是及時(shí)檢測(cè)數(shù)據(jù)發(fā)生的改動(dòng)。Microsoft SQL Server 2005 的完整版提供了notification功能,該功能向應(yīng)用程序通告某個(gè)數(shù)據(jù)查詢返回的結(jié)果已經(jīng)改變了。而對(duì)SQL Server 2005的Express版,以及更舊的版本而言,只有使用polling檢測(cè)系統(tǒng)了。不過(guò)還好,為polling設(shè)置必要的構(gòu)造是很簡(jiǎn)單的。

  祝編程快樂(lè)!

  作者簡(jiǎn)介

  Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來(lái)一直應(yīng)用 微軟Web技術(shù)。Scott是個(gè)獨(dú)立的技術(shù)咨詢顧問(wèn),培訓(xùn)師,作家,最近完成了將由Sams出版社出版的新作,24小時(shí)內(nèi)精通ASP.NET 2.0。他的聯(lián)系電郵為mitchell@4guysfromrolla.com,也可以通過(guò)他的博客http://ScottOnWriting.NET與他聯(lián)系。

 

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
OutputCache屬性詳解(四)— SqlDependency
.NET中的緩存知識(shí)總結(jié)
ASP.Net緩存總結(jié)及分析
數(shù)據(jù)庫(kù)緩存依賴詳解
一步一步學(xué)會(huì)在ASP.NET 4數(shù)據(jù)綁定控件中啟用動(dòng)態(tài)數(shù)據(jù)(翻譯) - longgel -...
ASP.NET 2.0輕松實(shí)現(xiàn)數(shù)據(jù)庫(kù)應(yīng)用開發(fā)
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服