佳木斯湛栽影视文化发展公司

主頁(yè) > 知識(shí)庫(kù) > 在ASP.NET 2.0中操作數(shù)據(jù)之五十六:使用ObjectDataSource緩存數(shù)據(jù)

在ASP.NET 2.0中操作數(shù)據(jù)之五十六:使用ObjectDataSource緩存數(shù)據(jù)

熱門(mén)標(biāo)簽:解決方案 智能手機(jī) 硅谷的囚徒呼叫中心 地方門(mén)戶網(wǎng)站 電子圍欄 呼叫中心 服務(wù)器配置 蘋(píng)果

導(dǎo)言

  就計(jì)算機(jī)科學(xué)而言,caching就是將所需要的數(shù)據(jù)或信息的備份放在某個(gè)地方,便于快速訪問(wèn)的這樣一個(gè)過(guò)程。以數(shù)據(jù)處理(data-driven)程序?yàn)槔绦虻拇蟛糠謺r(shí)間浪費(fèi)在數(shù)據(jù)查詢上。要提升這種程序的性能,通常的做法是將查詢結(jié)果存放在程序的存儲(chǔ)器里。

  ASP.NET 2.0提供了各種各樣的緩存方式。對(duì)web頁(yè)面和用戶控件可以通過(guò)output caching進(jìn)行緩存;同樣我們可以通過(guò)ObjectDataSource 和SqlDataSource控件,在控件級(jí)(control level)對(duì)數(shù)據(jù)進(jìn)行緩存;同時(shí),ASP.NET的data cache提供了豐富的緩存接口(caching API),供頁(yè)面開(kāi)發(fā)員通過(guò)編程緩存對(duì)象。在本文及接下來(lái)的3篇文章我們將對(duì)ObjectDataSource的緩存屬性以及data cache進(jìn)行考察;我們也將探究如何在啟動(dòng)時(shí)對(duì)application-wide數(shù)據(jù)進(jìn)行緩存,以及通過(guò)使用SQL cache dependencies對(duì)緩存數(shù)據(jù)刷新。

主要的緩存要點(diǎn)

  由于緩存通過(guò)將數(shù)據(jù)的副本放置在一個(gè)便于快速訪問(wèn)的地方來(lái)提高程序的總體性能。由于它僅僅是一個(gè)副本,當(dāng)源數(shù)據(jù)發(fā)生改變時(shí),副本不能同步更新。為此,頁(yè)面開(kāi)發(fā)員應(yīng)制定一個(gè)標(biāo)準(zhǔn)將其清除出內(nèi)存,可以使用如下的2種方法之一:

  Time-based標(biāo)準(zhǔn):向內(nèi)存添加的條目(item),只能在內(nèi)存里駐留固定或靈活(sliding)的一段時(shí)間。比如,開(kāi)發(fā)者可設(shè)定一個(gè)時(shí)間段,比如60秒,當(dāng)條目添加到內(nèi)存后,不管訪問(wèn)它的頻率有多高,60秒后就會(huì)被清除掉;如果是靈活(sliding)處理的話,當(dāng)最后一次被訪問(wèn)后,未再次被訪問(wèn)的時(shí)間一旦超出60秒,也會(huì)被清除掉。

  Dependency-based標(biāo)準(zhǔn):當(dāng)向內(nèi)存添加條目時(shí)為其分配一個(gè)從屬體(dependency),當(dāng)條目對(duì)應(yīng)的從屬體發(fā)生改變時(shí)將條目清除掉。從屬體可以是一個(gè)文件;另一個(gè)緩存條目;或者干脆是這兩者的混合體( combination);當(dāng)然還可以是SQL cache dependencies,它可以向內(nèi)存添加條目,當(dāng)源數(shù)據(jù)改變時(shí)將條目清除掉。我們將在接下來(lái)的文章《使用SQL緩存依賴項(xiàng)SqlCacheDependency 》里詳細(xì)考察。

  不管是哪種標(biāo)準(zhǔn),在條目被清除掉以前,我們都可以對(duì)其訪問(wèn)。如果內(nèi)存達(dá)到了它的極限,它會(huì)清除掉已有的條目后再添加新的條目。因此,當(dāng)處理緩存數(shù)據(jù)時(shí)很重要的一點(diǎn)是我們要充分考慮到緩存數(shù)據(jù)已被清除的可能。在下一篇文章《在分層架構(gòu)中緩存數(shù)據(jù)》我們考察采用哪種模式從內(nèi)存訪問(wèn)數(shù)據(jù)。

  緩存是提升程序性能的一種較為經(jīng)濟(jì)的方法,就像Steven Smith在他的文章《ASP.NET Caching: Techniques and Best Practices:》里闡述的一樣:“緩存是獲得‘上佳'性能的一種好方法,不需要太多的時(shí)間和分析?!?存儲(chǔ)器也便宜,要獲得你期望的性能,靠緩存技術(shù)你需要花30秒;靠?jī)?yōu)化代碼和數(shù)據(jù)庫(kù)你可能要幾天乃至幾周時(shí)間…”

  雖然緩存可以顯而易見(jiàn)的提升系統(tǒng)性能,但并不是適用于所有的應(yīng)用程序,比如某些實(shí)時(shí)(real-time)、頻繁更新數(shù)據(jù)的程序就不適合。
  但是對(duì)大部分程序而言,還是適用的。關(guān)于ASP.NET 2.0里的緩存的更多背景資料請(qǐng)參考ASP.NET 2.0 QuickStart Tutorials系列的Caching for Performance 部分。

第一步:創(chuàng)建Caching頁(yè)面

在我們開(kāi)始以前,首先讓我們花些時(shí)間來(lái)添加包括本篇在內(nèi)的最近四篇教程需要用到的頁(yè)面。我們先在項(xiàng)目中新建一個(gè)稱作Caching的文件夾,接下來(lái),為目錄新增以下幾個(gè)頁(yè)面,并配置為使用Site.master母板頁(yè)。

Default.aspx
ObjectDataSource.aspx
FromTheArchitecture.aspx
AtApplicationStartup.aspx
SqlCacheDependencies.aspx


圖1:創(chuàng)建相關(guān)的ASP.NET頁(yè)面

像其它文件夾一樣,Caching文件夾里的Default.aspx頁(yè)面將本系列的文章顯示出來(lái)。記得用戶控件SectionLevelTutorialListing.ascx提供該功能,設(shè)計(jì)模式里將其拖到頁(yè)面上。


圖2:為Default.aspx頁(yè)面添加用戶控件SectionLevelTutorialListing.ascx

最后,將這些頁(yè)面添加到Web.sitemap文件里,特別的,放在“Working with Binary Data” siteMapNode>:之后:

siteMapNode title="Caching" url="~/Caching/Default.aspx"
 description="Learn how to use the caching features of ASP.NET 2.0.">
 siteMapNode url="~/Caching/ObjectDataSource.aspx"
 title="ObjectDataSource Caching"
 description="Explore how to cache data directly from the
 ObjectDataSource control." />
 siteMapNode url="~/Caching/FromTheArchitecture.aspx"
 title="Caching in the Architecture"
 description="See how to cache data from within the
 architecture." />
 siteMapNode url="~/Caching/AtApplicationStartup.aspx"
 title="Caching Data at Application Startup"
 description="Learn how to cache expensive or infrequently-changing
 queries at the start of the application." />
 siteMapNode url="~/Caching/SqlCacheDependencies.aspx"
 title="Using SQL Cache Dependencies"
 description="Examine how to have data automatically expire from the
 cache when its underlying database data is modified." />
/siteMapNode>

完成Web.sitemap文件的更新后,讓我們?cè)跒g覽器里查看,左邊的菜單欄顯示caching章節(jié)的文章
圖3:網(wǎng)站地圖Site Map包含了Caching章節(jié)的文章

第二步:在Web Page頁(yè)面里展示產(chǎn)品

  本文考察怎樣使用ObjectDataSource控件內(nèi)置(built-in)的緩存功能。在開(kāi)始之前,我們首先需要?jiǎng)?chuàng)建一個(gè)頁(yè)面,用一個(gè)ObjectDataSource控件調(diào)用ProductsBLL class類獲取產(chǎn)品信息,再用GridView控件展示出來(lái)。

  首先打開(kāi)Caching文件夾里的ObjectDataSource.aspx頁(yè)面。從工具箱拖一個(gè)GridView控件到頁(yè)面,設(shè)置其ID為Products,再?gòu)闹悄軜?biāo)簽里選擇將其綁定到一個(gè)ObjectDataSource控件,ID為ProductsDataSource。設(shè)該ObjectDataSource使用ProductsBLL class類。


圖4:設(shè)置ObjectDataSource控件使用ProductsBLL Class類

  在本頁(yè)面,我們要?jiǎng)?chuàng)建一個(gè)允許編輯的GridView控件,當(dāng)ObjectDataSource控件里的緩存數(shù)據(jù)發(fā)生改變時(shí),我們可以通過(guò)GridView的界面查看到底會(huì)發(fā)生什么。在SELECT標(biāo)簽里選擇默認(rèn)的GetProducts()方法, 但是在UPDATE標(biāo)簽里選擇接受productName, unitPrice 和productID作為輸入?yún)?shù)的UpdateProduct()重載方法。


圖5:在UPDATE標(biāo)簽里選擇重載的UpdateProduct()方法

  最后,在INSERT和DELETE標(biāo)簽里選擇“(None)”,點(diǎn)完成按鈕。一旦完成“設(shè)置數(shù)據(jù)源向?qū)А保琕isual Studio會(huì)將ObjectDataSource控件的OldValuesParameterFormatString屬性設(shè)置為original_{0}。就像在前面的教程之16章《概述插入、更新和刪除數(shù)據(jù)》里探討的一樣,該屬性要么刪除掉,要么設(shè)置為{0},不然的話更新操作會(huì)報(bào)錯(cuò)。

  此外,完成向?qū)Ш?,Visual Studio會(huì)將產(chǎn)品的所有數(shù)據(jù)列添加到GridView控件,將除了ProductName, CategoryName和UnitPrice之外的所有綁定列(BoundFields)刪除。然后,分別將上述3列的HeaderText屬性改為Product”, “Category”和“Price”。由于ProductName是必需的,將ProductName列轉(zhuǎn)變成模板列(TemplateField),在EditItemTemplate里添加一個(gè)RequiredFieldValidator控件;同樣的,將UnitPrice列也轉(zhuǎn)換成模板列,并添加一個(gè)CompareValidator控件,確保用戶輸入的是大于或等于0的有效的貨幣值。除此以外,你還可以作一些界面上的改進(jìn),比如使UnitPrice值居中,或分別對(duì)UnitPrice的只讀和編輯界面作一些格式化的處理。

  在GridView的智能標(biāo)簽里點(diǎn)相關(guān)項(xiàng)啟動(dòng)編輯、分頁(yè)、排序功能。

  注意:想回顧怎樣自定義GridView的編輯界面嗎?請(qǐng)參考前面的文章之20《定制數(shù)據(jù)修改界面》 


圖6:?jiǎn)⒂肎ridView的編輯、排序、分頁(yè)功能。

完成GridView的修改后,GridView 和 ObjectDataSource的代碼聲明看起來(lái)像下面這樣:

asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
 DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
 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:TextBox>
 asp:RequiredFieldValidator
 ID="RequiredFieldValidator1" Display="Dynamic"
 ControlToValidate="ProductName" SetFocusOnError="True"
 ErrorMessage="You must provide a name for the product."
 runat="server">*/asp:RequiredFieldValidator>
 /EditItemTemplate>
 ItemTemplate>
 asp:Label ID="Label2" runat="server"
 Text='%# Bind("ProductName") %>'>/asp:Label>
 /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"
 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" runat="server"
 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="ProductsDataSource" runat="server"
 OldValuesParameterFormatString="{0}" 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>

如圖7所示,GridView列出了每個(gè)產(chǎn)品的name, category和price信息?;◣追昼姕y(cè)試頁(yè)面—對(duì)結(jié)果排序,查看分頁(yè),編輯某條記錄。


圖7:顯示每條記錄的Name, Category和Price信息

第三步:考察ObjectDataSource如何請(qǐng)求數(shù)據(jù)

  ID為Products的GridView通過(guò)調(diào)用名為ProductsDataSource的ObjectDataSource的Select()方法檢索數(shù)據(jù)并將它顯示出來(lái)。該ObjectDataSource創(chuàng)建業(yè)務(wù)邏輯層的ProductsBLL class類的一個(gè)實(shí)例并調(diào)用它的GetProducts()方法,該方法又調(diào)用數(shù)據(jù)訪問(wèn)層ProductsTableAdapter的GetProducts()方法。數(shù)據(jù)訪問(wèn)層連接到數(shù)據(jù)庫(kù)Northwind,并執(zhí)行已設(shè)置好了的SELECT查詢。查詢數(shù)據(jù)以NorthwindDataTable的形式返回到數(shù)據(jù)訪問(wèn)層,該DataTable對(duì)象再依次傳回到業(yè)務(wù)邏輯層,ObjectDataSource、GridView控件。GridView控件為DataTable里的每一數(shù)據(jù)行(DataRow)創(chuàng)建一個(gè)GridViewRow對(duì)象,每個(gè)GridViewRow對(duì)象最終被編譯為HTML返回到客戶端,呈現(xiàn)在訪問(wèn)者的瀏覽器里。

  任何時(shí)候,當(dāng)GridView控件需要綁定時(shí),按上述的事件發(fā)生順序執(zhí)行。比如,首次登錄頁(yè)面;將數(shù)據(jù)從一個(gè)頁(yè)面?zhèn)鬟f到另一個(gè)頁(yè)面;在GridView里排序;通過(guò)GridView內(nèi)建的編輯或刪除界面改動(dòng)數(shù)據(jù)。當(dāng)GridView的視圖(view sta被設(shè)為disabled時(shí),每次頁(yè)面回傳時(shí)也會(huì)對(duì)GridView重新綁定;當(dāng)然我們可以顯式地調(diào)用DataBind()方法來(lái)對(duì)GridView實(shí)施綁定。

  為了更清除地揭示從數(shù)據(jù)庫(kù)檢索數(shù)據(jù)的頻率,我們顯示一個(gè)消息,提示在某時(shí)程序在檢索數(shù)據(jù)。為此,在GridView控件上添加一個(gè)ID為ODSEvents的Label控件,清除其Text屬性,將其EnableViewState屬性設(shè)置為false。在Label控件下面再添加一個(gè)Button控件,設(shè)其Text屬性為“Postback”.


圖8:在GridView上添加Label 和 Button控件

在整個(gè)數(shù)據(jù)檢索過(guò)程中,首先觸發(fā)ObjectDataSource的Selecting事件,并調(diào)用其對(duì)應(yīng)的已設(shè)置好的方法。為該事件創(chuàng)建一個(gè)事件處理器,添加如下的代碼:

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

  每當(dāng)ObjectDataSource開(kāi)始檢索數(shù)據(jù)時(shí),Label控件都會(huì)顯示文本“Selecting event fired”.

  在瀏覽器訪問(wèn)該頁(yè)面。當(dāng)首次登錄時(shí),文本“Selecting event fired”就會(huì)顯示出來(lái)。點(diǎn)“Postback”按鈕時(shí),我們注意到文本消失了(前提是你將GridView的EnableViewState屬性設(shè)置為默認(rèn)值true)。這是因?yàn)楫?dāng)頁(yè)面回傳時(shí),GridView通過(guò)它的視圖狀態(tài)(view state)載入數(shù)據(jù)進(jìn)行重建(reconstructed),因此不再需要通過(guò)ObjectDataSource檢索數(shù)據(jù)庫(kù)來(lái)得到數(shù)據(jù)進(jìn)行重建。然而,排序、分頁(yè)、編輯等都會(huì)促使GridView重新綁定到數(shù)據(jù)源,因此,文本“Selecting event fired”又出現(xiàn)了。


圖9:當(dāng)GridView重新綁定到數(shù)據(jù)源時(shí),顯示文本“Selecting event fired”


圖10:點(diǎn)“Postback” 按鈕導(dǎo)致GridView從視圖狀態(tài)“View State”獲取數(shù)據(jù)

  每次分頁(yè)、排序時(shí)都需要從數(shù)據(jù)庫(kù)檢索數(shù)據(jù),這看起來(lái)有點(diǎn)浪費(fèi)資源。即便GridView不支持排序和分頁(yè),任何人每次第一次登錄頁(yè)面時(shí)都需要從數(shù)據(jù)庫(kù)檢索數(shù)據(jù)(如果將view state設(shè)置為disabled的話,每次頁(yè)面回轉(zhuǎn)也會(huì)檢索數(shù)據(jù))。如果GridView對(duì)所有用戶顯示的數(shù)據(jù)都是一樣話,那么額外的數(shù)據(jù)庫(kù)查詢是浪費(fèi)。我們可以對(duì)GetProducts()方法返回的數(shù)據(jù)進(jìn)行緩存,再將GridView綁定到這些緩存數(shù)據(jù)。

第四步:用ObjectDataSource緩存數(shù)據(jù)

僅僅簡(jiǎn)單的設(shè)置某些屬性,我們就可以讓ObjectDataSource對(duì)它的檢索數(shù)據(jù)自動(dòng)的進(jìn)行緩存。以下總結(jié)了ObjectDataSource控件的與緩存相關(guān)的屬性:

EnableCaching—必須設(shè)置為true,默認(rèn)為false.

CacheDuration—緩存時(shí)間,以秒為單位。默認(rèn)為0,只有當(dāng)EnableCaching屬性設(shè)置為true,且CacheDuration設(shè)為大于0的值時(shí)ObjectDataSource控件才會(huì)緩存數(shù)據(jù)。

CacheExpirationPolicy—可設(shè)置為Absolute 或 Sliding。如果為Absolute,當(dāng)它設(shè)為多少秒時(shí),ObjectDataSource就會(huì)對(duì)檢索的數(shù)據(jù)緩存多少秒;如果為Sliding,當(dāng)它設(shè)為多少秒時(shí),一旦超過(guò)那么多秒沒(méi)有對(duì)緩存數(shù)據(jù)進(jìn)行訪問(wèn),就終止緩存。默認(rèn)為Absolute。

CacheKeyDependency—用該屬性將ObjectDataSource的緩存條目(entry)與現(xiàn)有的緩存從屬體關(guān)聯(lián)起來(lái)。利用可以它將緩存條目提前從內(nèi)存清除掉。絕大多數(shù)情況下用該屬性把SQL cache dependency與ObjectDataSource的緩存關(guān)聯(lián)起來(lái)。這個(gè)話題我們將在后面的教程《使用SQL緩存依賴項(xiàng)SqlCacheDependency 》考察。

讓我們?cè)O(shè)置ID為ProductsDataSource的ObjectDataSource 的數(shù)據(jù)緩存時(shí)間為30秒。設(shè)其EnableCaching屬性為true;設(shè)其CacheDuration屬性為30;CacheExpirationPolicy屬性為默認(rèn)的Absolute。


圖11:設(shè)置ObjectDataSource的緩存時(shí)間為30秒

  保存你的設(shè)置,并在瀏覽器里查看。當(dāng)你第一次登錄頁(yè)面時(shí),文本“Selecting event fired”會(huì)顯示出來(lái),因?yàn)樵紨?shù)據(jù)還未緩存。但你點(diǎn)“Postback”按鈕,或進(jìn)行分頁(yè),排序,或點(diǎn)編輯、取消按鈕時(shí),文本“Selecting event fired”就不會(huì)顯示出來(lái)了。原因是只有當(dāng)ObjectDataSource控件檢索數(shù)據(jù)時(shí)才會(huì)觸發(fā)Selecting事件;如果ObjectDataSource控件是從緩存里面獲取數(shù)據(jù)的話就不會(huì)觸發(fā)Selecting事件。

  過(guò)了30秒后,數(shù)據(jù)將從內(nèi)存清除;或者調(diào)用ObjectDataSource控件的Insert, Update,或Delete方法的話數(shù)據(jù)也會(huì)被清除掉。因此,過(guò)了30秒后或點(diǎn)擊“Update”按鈕,編輯,取消按鈕,或排序、分頁(yè)的話就會(huì)促使ObjectDataSource檢索數(shù)據(jù),觸發(fā)Selecting事件,文本“Selecting event fired”又會(huì)顯示出來(lái)。最后,再對(duì)檢索得到的數(shù)據(jù)進(jìn)行緩存。

  注意:如果你看到文本“Selecting event fired”頻繁的出現(xiàn),很可能是內(nèi)存容量太小。如果沒(méi)有足夠的容量,ObjectDataSource添加到內(nèi)存的數(shù)據(jù)可能被清除掉了。如果ObjectDataSource沒(méi)有或者只是偶爾地對(duì)數(shù)據(jù)緩存,請(qǐng)關(guān)閉一些應(yīng)用程序來(lái)釋放掉內(nèi)存,然后再試一次。

  圖12揭示了ObjectDataSource的緩存流程。當(dāng)文本“Selecting event fired”出現(xiàn)在屏幕上時(shí),那是因?yàn)閿?shù)據(jù)沒(méi)有在緩存里找到,必須進(jìn)行相關(guān)檢索。當(dāng)文本消失時(shí),那是因?yàn)閿?shù)據(jù)進(jìn)行了緩存。當(dāng)從緩存得到了所需的數(shù)據(jù)時(shí),沒(méi)有任何數(shù)據(jù)查詢執(zhí)行。


圖12:ObjectDataSource在Data Cache里存儲(chǔ)和獲取數(shù)據(jù)

  每一個(gè)ASP.NET應(yīng)用程序有它自己的數(shù)據(jù)緩存實(shí)例,所有的頁(yè)面和用戶都可以進(jìn)行訪問(wèn)。那意味著對(duì)于ObjectDataSource控件緩存的數(shù)據(jù),所有登錄該頁(yè)面的用戶都可以訪問(wèn)。來(lái)做個(gè)驗(yàn)證,在一個(gè)瀏覽器里打開(kāi)ObjectDataSource.aspx頁(yè)面,當(dāng)?shù)谝淮蔚卿浽擁?yè)面時(shí),文本“Selecting event fired”顯現(xiàn)出來(lái)(假定前面測(cè)試時(shí)緩存的數(shù)據(jù)到此時(shí)已經(jīng)被清除掉了)。再開(kāi)第二個(gè)瀏覽器,將第一個(gè)瀏覽器里的URL地址拷貝、粘貼過(guò)來(lái)。在第二個(gè)瀏覽器里,文本“Selecting event fired”并沒(méi)有顯示出來(lái),因?yàn)樗褂玫氖堑谝粋€(gè)瀏覽器頁(yè)面緩存的數(shù)據(jù)。

  當(dāng)向內(nèi)存添加檢索數(shù)據(jù)時(shí),ObjectDataSource要用到一個(gè)叫cache key的值,該值包括:CacheDuration 和 CacheExpirationPolicy屬性的值;ObjectDataSource調(diào)用的業(yè)務(wù)對(duì)象的類型(type),它由TypeName 屬性指定(比如:ProductsBLL);SelectMethod 屬性的值,以及SelectParameters參數(shù)集里參數(shù)的name 和 values;StartRowIndex 和 MaximumRows屬性的值,它用來(lái)執(zhí)行用戶自定義分頁(yè)(custom paging)。

  將這些屬性值組合在一起構(gòu)成cache key值是為了對(duì)每一個(gè)緩存條目提供唯一的標(biāo)識(shí)值。比如,在前面的教程里,我們使用ProductsBLL類的GetProductsByCategoryID(categoryID)方法來(lái)獲取某個(gè)指定類的所有產(chǎn)品。假如一個(gè)用戶在頁(yè)面查看飲料類(其CategoryID值為1)的產(chǎn)品信息,如果ObjectDataSource控件在進(jìn)行數(shù)據(jù)緩存時(shí)忽略SelectParameters的值,當(dāng)另一個(gè)用戶登錄頁(yè)面查看調(diào)味品類的產(chǎn)品信息時(shí),恰好飲料類產(chǎn)品信息正好緩存在內(nèi)存里,第二個(gè)用戶將會(huì)看到飲料類的產(chǎn)品信息,而非他想要的調(diào)味品類的產(chǎn)品信息。所以,當(dāng)cache key值包含electParameters的值的話,ObjectDataSource緩存數(shù)據(jù)的時(shí)候就可以將調(diào)味品類和飲料類區(qū)分開(kāi)來(lái)。

數(shù)據(jù)更新不同步(Stale Data)問(wèn)題

  當(dāng)調(diào)用ObjectDataSource控件的Insert, Update和 Delete其中一個(gè)方法時(shí),它都會(huì)將緩存條目從內(nèi)存清除掉。這樣做的好處在于當(dāng)從頁(yè)面修改數(shù)據(jù)時(shí)將緩存的舊數(shù)據(jù)清除掉。然而,ObjectDataSource還是可能有將“未更新數(shù)據(jù)”(也就是源數(shù)據(jù)已經(jīng)發(fā)生改變,而緩存的數(shù)據(jù)沒(méi)同步更新)顯示出來(lái)的情況。最簡(jiǎn)單的例子是直接從數(shù)據(jù)庫(kù)修改數(shù)據(jù),比如某個(gè)數(shù)據(jù)庫(kù)管理員運(yùn)行一個(gè)腳本,修改數(shù)據(jù)庫(kù)里的某些記錄。

  在此,我們探討一種微妙的情況。雖然調(diào)用ObjectDataSource的數(shù)據(jù)修改方法時(shí)它會(huì)將緩存數(shù)據(jù)清除掉,但清除的是那些與ObjectDataSource的“屬性組合值”(combination of property)相匹配的緩存條目(比如CacheDuration, TypeName, SelectMethod等)。假如你有2個(gè)ObjectDataSources控件,它們更新相同的數(shù)據(jù),當(dāng)使用不同的SelectMethods 或 SelectParameters,當(dāng)?shù)谝粋€(gè)ObjectDataSources控件更新某一行記錄而清除該行對(duì)應(yīng)的緩存數(shù)據(jù)時(shí),第二個(gè)ObjectDataSources控件仍然使用該行對(duì)應(yīng)的緩存數(shù)據(jù)。我們來(lái)做個(gè)驗(yàn)證,創(chuàng)建一個(gè)頁(yè)面,包含可編輯的GridView控件,其對(duì)應(yīng)的ObjectDataSource控件設(shè)置為使用緩存,且調(diào)用ProductsBLL類的GetProducts()方法來(lái)獲取數(shù)據(jù)。在本頁(yè)(或另外創(chuàng)建一個(gè)頁(yè)面)再添加GridView 和ObjectDataSource控件,但是設(shè)置第二個(gè)ObjectDataSource控件調(diào)用GetProductsByCategoryID(categoryID)方法。由于這2個(gè)ObjectDataSource控件的SelectMethod屬性不同,因此它們各自有各自不同的緩存值。如果你在第一個(gè)GridView控件里編輯某個(gè)產(chǎn)品,然后在第二個(gè)GridView控件里重新綁定數(shù)據(jù)(比如分頁(yè)、排序等),我們?cè)诘诙€(gè)GridView控件里看到該產(chǎn)品的值依然是“老的緩存數(shù)據(jù)”(而并不是第一個(gè)GridView控件修改后的值)

  簡(jiǎn)而言之,如果你樂(lè)于使用“老的緩存數(shù)據(jù)”,那只有使用基于時(shí)間的緩存時(shí)間值(time-based expiries,也就是設(shè)置具體的緩存時(shí)間長(zhǎng)度),如果對(duì)數(shù)據(jù)及時(shí)更新要求很高的話,將緩存時(shí)間設(shè)短點(diǎn)。如果不允許使用“老的緩存數(shù)據(jù)”的話,要么放棄緩存,要么使用SQL cache dependencies(你可以認(rèn)為它是你緩存的數(shù)據(jù)庫(kù)數(shù)據(jù))。我們將在后面探討SQL cache dependencies。

總結(jié):

  在本文我們考察了ObjectDataSource內(nèi)建的緩存功能。僅僅設(shè)置很少的屬性,我們可以將ObjectDataSource調(diào)用SelectMethod方法得到的數(shù)據(jù)進(jìn)行緩存。其CacheDuration 和 CacheExpirationPolicy屬性指定了緩存的時(shí)間和類型(absolute或sliding)。而CacheKeyDependency屬性將ObjectDataSource的緩存實(shí)體與現(xiàn)有的緩存從屬體(cache dependency)關(guān)聯(lián)起來(lái),一般是SQL cache dependencies。

  因?yàn)镺bjectDataSource只是簡(jiǎn)單地進(jìn)行數(shù)據(jù)緩存,我們可以通過(guò)編程實(shí)現(xiàn)ObjectDataSource內(nèi)建的這種功能。不過(guò)在表現(xiàn)層這樣做沒(méi)有意義,因?yàn)镺bjectDataSource控件提供了該功能。不過(guò)我們可以在體系結(jié)構(gòu)的其它層次實(shí)現(xiàn)緩存功能。為此,我們需要一個(gè)邏輯,它與ObjectDataSource調(diào)用的相同。在下一篇文章我們將考察如何在體系結(jié)構(gòu)內(nèi)部編程處理數(shù)據(jù)緩存。

  祝編程快樂(lè)!

作者簡(jiǎn)介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的書(shū),是4GuysFromRolla.com的創(chuàng)始人,自1998年以來(lái)一直應(yīng)用 微軟Web技術(shù)。大家可以點(diǎn)擊查看全部教程《[翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程》,希望對(duì)大家的學(xué)習(xí)ASP.NET有所幫助。

您可能感興趣的文章:
  • 在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之五十八:在程序啟動(dòng)階段緩存數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之五十九:使用SQL緩存依賴項(xiàng)SqlCacheDependency
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十:創(chuàng)建一個(gè)自定義的Database-Driven Site Map Provider
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十一:在事務(wù)里對(duì)數(shù)據(jù)庫(kù)修改進(jìn)行封裝
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十二:GridView批量更新數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十三:GridView實(shí)現(xiàn)批量刪除數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十四:GridView批量添加數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十五:在TableAdapters中創(chuàng)建新的存儲(chǔ)過(guò)程
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十六:在TableAdapters中使用現(xiàn)有的存儲(chǔ)過(guò)程

標(biāo)簽:德宏 呂梁 泰安 佳木斯 喀什 玉林 房產(chǎn)

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《在ASP.NET 2.0中操作數(shù)據(jù)之五十六:使用ObjectDataSource緩存數(shù)據(jù)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266
    黎城县| 阿勒泰市| 丽江市| 宁强县| 平武县| 安庆市| 吉林市| 和平县| 巨鹿县| 峨眉山市| 城步| 深州市| 环江| 黄冈市| 高雄市| 民权县| 葫芦岛市| 苗栗县| 保亭| 浠水县| 海阳市| 四会市| 西贡区| 寿阳县| 同心县| 威信县| 贺州市| 孙吴县| 四川省| 云林县| 宜兰市| 阿合奇县| 丽江市| 唐海县| 汽车| 无锡市| 西峡县| 汝南县| 宜兰市| 吴旗县| 大厂|