午夜视频免费看_日韩三级电影网站_国产精品久久一级_亚洲一级在线播放_人妻体内射精一区二区三区_91夜夜揉人人捏人人添红杏_91福利在线导航_国产又粗又猛又黄又爽无遮挡_欧美日韩一区在线播放_中文字幕一区二区三区四区不卡 _日日夜夜精品视频免费观看_欧美韩日一区二区三区

主頁(yè) > 知識(shí)庫(kù) > 在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)

在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)

熱門標(biāo)簽:西寧呼叫中心外呼系統(tǒng)線路商 臨沂智能電話機(jī)器人加盟 400電話辦理怎么樣 外呼電話機(jī)器人成本 網(wǎng)絡(luò)電話外呼系統(tǒng)上海 地圖標(biāo)注軟件免費(fèi)下載 蘇州如何辦理400電話 聯(lián)通官網(wǎng)400電話辦理 百應(yīng)電話機(jī)器人外呼系統(tǒng)

導(dǎo)言:

  正如前面章節(jié)所言,緩存ObjectDataSource的數(shù)據(jù)只需要簡(jiǎn)單的設(shè)置一些屬性。然而,它是在表現(xiàn)層對(duì)數(shù)據(jù)緩存,這就與ASP.NET page頁(yè)面緩存策略(caching policies)緊密的耦合(tightly couples)起來(lái)。我們對(duì)體系機(jī)構(gòu)分層的原因之一便是打破這種耦合。拿業(yè)務(wù)邏輯層為例,將業(yè)務(wù)邏輯從ASP.NET頁(yè)面脫離出來(lái);而數(shù)據(jù)訪問(wèn)層將數(shù)據(jù)訪問(wèn)的細(xì)節(jié)ASP.NET頁(yè)面脫離出來(lái)。從某種意義來(lái)說(shuō),將業(yè)務(wù)邏輯和數(shù)據(jù)訪問(wèn)細(xì)節(jié)脫離出來(lái)是首先,這樣的話使系統(tǒng)更易讀、易維護(hù)、易修改,便于按模塊分工—比如,表現(xiàn)層的開(kāi)發(fā)者對(duì)數(shù)據(jù)庫(kù)的細(xì)節(jié)不甚了解也不妨礙其開(kāi)發(fā)工作。當(dāng)然,將緩存策略從表現(xiàn)層脫離出來(lái)也有類似的好處。

  本文我們將對(duì)層次機(jī)構(gòu)進(jìn)行擴(kuò)充,新添一個(gè)緩存層(Caching Layer,簡(jiǎn)稱CL)以實(shí)施緩存策略。該緩存層包括一個(gè)ProductsCL類,該類用類似 GetProducts(), GetProductsByCategoryID(categoryID)等方法來(lái)訪問(wèn)產(chǎn)品信息。調(diào)用這些方法時(shí)先從內(nèi)存檢索數(shù)據(jù),如果內(nèi)存為空則調(diào)用業(yè)務(wù)邏輯層BLL里的ProductsBLL類的相應(yīng)方法,再?gòu)臄?shù)據(jù)訪問(wèn)層DAL返回獲取的數(shù)據(jù)。該P(yáng)roductsCL類的方法從業(yè)務(wù)邏輯層BLL獲取數(shù)據(jù)后先對(duì)數(shù)據(jù)緩存后再返回。

如圖1所示,緩存層CL位于表現(xiàn)層和業(yè)務(wù)邏輯層。


圖1:在我們的體系結(jié)構(gòu)中緩存層(CL)是單獨(dú)的一層

第一步:創(chuàng)建緩存層的類

  在本文,我們創(chuàng)建的緩存層僅僅包含一個(gè)ProductsCL類,它只有幾個(gè)方法。
  完整的緩存層還應(yīng)該包含CategoriesCL, EmployeesCL, 和SuppliersCL類。有了業(yè)務(wù)邏輯層BLL和數(shù)據(jù)訪問(wèn)層DAL,緩存層完全可以當(dāng)成一個(gè)單獨(dú)的類庫(kù)工程(Class Library project),不過(guò)我們將它作為App_Code文件夾里的一個(gè)類來(lái)處理。

  為了更好的將緩存層類和DAL類、BLL類區(qū)分開(kāi),我們?cè)贏pp_Code文件夾里創(chuàng)建一個(gè)新的子文件夾。在資源管理器里右擊App_Code文件夾,選擇“新文件夾”,命名為CL,在里面添加新類ProductsCL.cs


圖2:添加名為CL的文件夾和名為ProductsCL.cs的類

  跟BLL里的ProductsBLL類一樣,ProductsCL類應(yīng)該包含相同的數(shù)據(jù)訪問(wèn)和修改方法。不過(guò)在本文,我們只創(chuàng)建GetProducts()方法(在第3步)和GetProductsByCategoryID(categoryID)方法(在第4步)。你可以在空閑的時(shí)候?qū)roductsCL類進(jìn)行完善,并創(chuàng)建相應(yīng)的CategoriesCL, EmployeesCL和 SuppliersCL類

第二步:對(duì)Data Cache進(jìn)行讀和寫

  ObjectDataSource的緩存屬性使用ASP.NET data cache來(lái)存儲(chǔ)從BLL獲取的數(shù)據(jù)。要訪問(wèn)data cache,可以從ASP.NET頁(yè)面的code-behind classes類或體系結(jié)構(gòu)層(architecture)的類來(lái)訪問(wèn)。要通過(guò)ASP.NET頁(yè)面的code-behind classes類對(duì)data cache進(jìn)行讀寫,可使用如下模式:

// Read from the cache(讀)
object value = Cache["key"];
// Add a new item to the cache(寫)
Cache["key"] = value;
Cache.Insert(key, value);
Cache.Insert(key, value, CacheDependency);
Cache.Insert(key, value, CacheDependency, DateTime, TimeSpan);

  Cache class類的Insert方法可以有很多的重載。Cache["key"] = value 和 Cache.Insert(key, value)是相同的,都是向cache添加一個(gè)條目(item),不過(guò)沒(méi)有指定expiry(可以理解為緩存持續(xù)時(shí)間)。更具代表性的是,在我們向cache添加條目的時(shí)候指定一個(gè)expiry,它要么是dependency(從屬體),要么是time-based expiry,又或者兩者兼而有之,比如上面的最后2個(gè)表達(dá)式。

  如果所需的數(shù)據(jù)存儲(chǔ)在內(nèi)存的話,首先調(diào)用緩存層的方法返回?cái)?shù)據(jù)。如果不在內(nèi)存的話就調(diào)用BLL里相應(yīng)的方法。數(shù)據(jù)先緩存再返回。就像下面的流程表解析的一樣:


圖3:如果數(shù)據(jù)存在于內(nèi)存的話就調(diào)用緩存層的方法。

上圖的流程可用如下的模式:

Type instance = Cache["key"] as Type;
if (instance == null)
{
 instance = BllMethodToGetInstance();
 Cache.Insert(key, instance, ...);
}
return instance;

  其中,Type是緩存在內(nèi)存中的數(shù)據(jù)的類型——具體到本文,也就是Northwind.ProductsDataTable;此外,key用于唯一地標(biāo)識(shí)緩存的每一個(gè)條目。如果指定了key值的那個(gè)條目不在內(nèi)存中,那么instance就為null,然后用BLL類的某恰當(dāng)?shù)姆椒▉?lái)檢索數(shù)據(jù),將獲得的數(shù)據(jù)緩存到內(nèi)存。將instance返回后,它將包含一個(gè)對(duì)數(shù)據(jù)的引用(reference to the data),數(shù)據(jù)要么來(lái)自內(nèi)存,要么是BLL類的返回?cái)?shù)據(jù)。

  當(dāng)訪問(wèn)內(nèi)存時(shí),請(qǐng)務(wù)必使用上述模式。下面的這個(gè)模式,咋一看好像和上面的模式一模一樣,但是有一個(gè)細(xì)微的區(qū)別,它存在一個(gè)race condition(可以理解為不易察覺(jué)的隱式缺陷)。race condition很難調(diào)試,因?yàn)樗皇桥紶柊l(fā)生,而且再次發(fā)生的可能性也小。如下:

if (Cache["key"] == null)
{
 Cache.Insert(key, BllMethodToGetInstance(), ...);
}
return Cache["key"];

  再一個(gè)就是,上述模式不是在局部變量里存儲(chǔ)緩存條目的引用,而是在條件語(yǔ)句里直接訪問(wèn)數(shù)據(jù),在return語(yǔ)句里直接返回?cái)?shù)據(jù)。設(shè)想這種情況,開(kāi)始運(yùn)行代碼時(shí)Cache["key"]是non-null的,但在運(yùn)行return語(yǔ)句前,系統(tǒng)將其從內(nèi)存里清除掉,那么代碼就會(huì)返回一個(gè)null值,而不是我們期望的某種類型的對(duì)象。

  注意:如果僅僅是對(duì)data cache進(jìn)行讀或?qū)懺L問(wèn),你沒(méi)有必要進(jìn)行同步訪問(wèn)(synchronize thread access);當(dāng)然,如果你需要對(duì)內(nèi)存里的數(shù)據(jù)進(jìn)行多重操作(multiple operations),你還是應(yīng)該實(shí)施鎖定(lock),或其它的機(jī)制。

如果要從data cache里清除某個(gè)條目,可以用Remove方法,比如:

Cache.Remove(key);

第三步:從ProductsCL類返回產(chǎn)品信息

  在本文,我們要在ProductsCL類里用2個(gè)方法來(lái)返回產(chǎn)品信息: GetProducts()和 GetProductsByCategoryID(categoryID). 和業(yè)務(wù)邏輯層里的ProductsBL類相似,緩存層里的GetProducts()方法返回一個(gè)Northwind.ProductsDataTable對(duì)象,來(lái)獲取所有產(chǎn)品的信息;而GetProductsByCategoryID(categoryID)方法返回的是某個(gè)特定類別的所有產(chǎn)品。

如下的代碼是ProductsCL類里的部分方法:

[System.ComponentModel.DataObject]
public class ProductsCL
{
 private ProductsBLL _productsAPI = null;
 protected ProductsBLL API
 {
 get
 {
 if (_productsAPI == null)
 _productsAPI = new ProductsBLL();

 return _productsAPI;
 }
 }
 
 [System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select, true)]
 public Northwind.ProductsDataTable GetProducts()
 {
 const string rawKey = "Products";

 // See if the item is in the cache
 Northwind.ProductsDataTable products = _
 GetCacheItem(rawKey) as Northwind.ProductsDataTable;
 if (products == null)
 {
 // Item not found in cache - retrieve it and insert it into the cache
 products = API.GetProducts();
 AddCacheItem(rawKey, products);
 }

 return products;
 }
 
 [System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select, false)]
 public Northwind.ProductsDataTable GetProductsByCategoryID(int categoryID)
 {
 if (categoryID  0)
 return GetProducts();
 else
 {
 string rawKey = string.Concat("ProductsByCategory-", categoryID);

 // See if the item is in the cache
 Northwind.ProductsDataTable products = _
 GetCacheItem(rawKey) as Northwind.ProductsDataTable;
 if (products == null)
 {
 // Item not found in cache - retrieve it and insert it into the cache
 products = API.GetProductsByCategoryID(categoryID);
 AddCacheItem(rawKey, products);
 }

 return products;
 }
 }
}

  首先,注意運(yùn)用到類(class)和方法(methods)上的屬性 DataObject和 DataObjectMethodAttribute ;這些屬性服務(wù)于ObjectDataSource的設(shè)置向?qū)В赋瞿切╊惡头椒☉?yīng)該出現(xiàn)在向?qū)У脑O(shè)置步驟里。因?yàn)镺bjectDataSource控件要在表現(xiàn)層訪問(wèn)這些類和方法,所以我添加了這些屬性,方便向?qū)гO(shè)置。關(guān)于這些屬性及其作用,請(qǐng)參閱本教程第2章《創(chuàng)建一個(gè)業(yè)務(wù)邏輯層》。

  在GetProducts() 和 GetProductsByCategoryID(categoryID)方法里,GetCacheItem(key)返回的數(shù)據(jù)賦值給一個(gè)局部變量。GetCacheItem(key)方法根據(jù)指定的key值在內(nèi)存查找對(duì)應(yīng)的緩存條目;如果沒(méi)找到,則用ProductsBLL類里相應(yīng)的方法來(lái)檢索數(shù)據(jù),并用AddCacheItem(key, value)方法將獲取的數(shù)據(jù)緩存到內(nèi)存。

GetCacheItem(key) 和 AddCacheItem(key, value)方法分別對(duì)data cache進(jìn)行讀、寫操作。GetCacheItem(key)相對(duì)簡(jiǎn)單,它根據(jù)傳入的key值,從Cache類返回?cái)?shù)據(jù),如下:

private object GetCacheItem(string rawKey)
{
 return HttpRuntime.Cache[GetCacheKey(rawKey)];
}

private readonly string[] MasterCacheKeyArray = {"ProductsCache"};
private string GetCacheKey(string cacheKey)
{
 return string.Concat(MasterCacheKeyArray[0], "-", cacheKey);
}

  GetCacheItem(key)并沒(méi)有直接使用我們提供的key值,而是調(diào)用GetCacheKey(key)方法,因?yàn)樵摲椒ǜ鶕?jù)“ProductsCache-”返回key;在上述代碼中,MasterCacheKeyArray用于存儲(chǔ)字符串“ProductsCache”。當(dāng)然,AddCacheItem(key, value)方法也會(huì)用到MasterCacheKeyArray,我們稍后會(huì)看到。

  在ASP.NET頁(yè)面后臺(tái)代碼類(code-behind class),我們可以使用Page類的Cache屬性來(lái)訪問(wèn)data cache ,就像我們?cè)诘?步里的表達(dá)式:Cache["key"] = value一樣;而在體系結(jié)構(gòu)的類(注:具體到本文,就是緩存層類(ProductsCL),我們可以通過(guò)2種方式來(lái)訪問(wèn):HttpRuntime.Cache 或 HttpContext.Current.Cache ;在Peter Johnson的博客里有一篇文章《HttpRuntime.Cache vs. HttpContext.Current.Cache》(http://weblogs.asp.net/pjohnson/archive/2006/02/06/437559.aspx),探討了HttpRuntim與相對(duì)于HttpContext.Current的優(yōu)點(diǎn);在此,我們的ProductsCL類將使用HttpRuntime.
注意:如果你是使用的類庫(kù)工程(Class Library projects),一定要記得引用System.Web才能使用HttpRuntime 和 HttpContext類。

  如果沒(méi)有在內(nèi)存找到數(shù)據(jù),ProductsCL類將從業(yè)務(wù)邏輯層BLL獲取數(shù)據(jù),并使用AddCacheItem(key, value)對(duì)數(shù)據(jù)進(jìn)行緩存,可以用下面的代碼向內(nèi)存添加緩存數(shù)據(jù),其緩存時(shí)間為60秒:

const double CacheDuration = 60.0;

private void AddCacheItem(string rawKey, object value)
{
 HttpRuntime.Cache.Insert(GetCacheKey(rawKey), value, null,
 DateTime.Now.AddSeconds(CacheDuration), Caching.Cache.NoSlidingExpiration);
}

  其中,DateTime.Now.AddSeconds(CacheDuration)指定了緩存時(shí)間—60秒;而 System.Web.Caching.Cache.NoSlidingExpiration指明了不存在可變緩存時(shí)間(no sliding expiration).雖然Insert()方法可以包含絕對(duì)時(shí)間和可變時(shí)間(absolute and sliding expiry)2種定義緩存時(shí)間的輸入?yún)?shù),但是你只能指定其中一個(gè),如果你同時(shí)指定絕對(duì)時(shí)間和可變時(shí)間2個(gè)參數(shù)的話,Insert()方法會(huì)拋出一ArgumentException 異常。
注意:直接執(zhí)行AddCacheItem(key, value)方法會(huì)有一些弊端,我們將在第4步解釋并修正。

第4步:當(dāng)數(shù)據(jù)被修改時(shí)使緩存失效

  除了數(shù)據(jù)檢索方法外,緩存層還應(yīng)該包含插入、更新、刪除數(shù)據(jù)的方法。緩存層的數(shù)據(jù)修改方法并不是修改緩存的數(shù)據(jù),而是調(diào)用業(yè)務(wù)邏輯層的相應(yīng)方法,然后使緩存數(shù)據(jù)失效。就像前面章節(jié)探討的那樣,當(dāng)激活ObjectDataSource的緩存屬性時(shí),便可調(diào)用它的Insert, Update或Delete方法。

下面的UpdateProduct方法,說(shuō)明了如何在緩存層CL執(zhí)行數(shù)據(jù)修改方法:

[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
 bool result = API.UpdateProduct(productName, unitPrice, productID);

 // TODO: Invalidate the cache

 return result;
}

  在業(yè)務(wù)邏輯層的方法返回?cái)?shù)據(jù)以前,我們需要將緩存的數(shù)據(jù)失效。不過(guò),這并非易事,無(wú)論P(yáng)roductsCL class's GetProducts()還是GetProductsByCategoryID(categoryID)都會(huì)向內(nèi)存添加條目,并且GetProductsByCategoryID(categoryID)方法會(huì)為每種類別添加幾個(gè)條目(因?yàn)槊糠N類別有幾種甚至更多的產(chǎn)品)。

  要使緩存數(shù)據(jù)失效,我們需要將ProductsCL類添加的所有條目刪除。為此,在AddCacheItem(key, value)方法里,當(dāng)添加條目時(shí)為其指定一個(gè)緩存從屬體(cache dependency)。一般來(lái)說(shuō),緩存從屬體可以是內(nèi)存里的另一個(gè)條目;文件系統(tǒng)里的一個(gè)文件;又或者是Microsoft SQLServer database數(shù)據(jù)庫(kù)里的數(shù)據(jù)。當(dāng)從屬體發(fā)生改變,或者從內(nèi)存里移除時(shí),其對(duì)應(yīng)的緩存條目會(huì)自動(dòng)的從內(nèi)存刪除。在本教程,當(dāng)ProductsCL類向內(nèi)存添加條目時(shí),我們創(chuàng)建一個(gè)額外的條目作為其從屬體。由此,要?jiǎng)h除緩存條目,僅僅移除這些從屬體即可。

  我們來(lái)更改AddCacheItem(key, value)方法,當(dāng)用該方法向內(nèi)存添加緩存數(shù)據(jù)時(shí),使每個(gè)條目與一個(gè)從屬體(cache dependency)對(duì)應(yīng)起來(lái)。

private void AddCacheItem(string rawKey, object value)
{
 System.Web.Caching.Cache DataCache = HttpRuntime.Cache;

 // Make sure MasterCacheKeyArray[0] is in the cache - if not, add it
 if (DataCache[MasterCacheKeyArray[0]] == null)
 DataCache[MasterCacheKeyArray[0]] = DateTime.Now;

 // Add a CacheDependency
 System.Web.Caching.CacheDependency dependency =
 new CacheDependency(null, MasterCacheKeyArray);
 DataCache.Insert(GetCacheKey(rawKey), value, dependency,
 DateTime.Now.AddSeconds(CacheDuration),
 System.Web.Caching.Cache.NoSlidingExpiration);
}

  MasterCacheKeyArray是一個(gè)字符串?dāng)?shù)組,用來(lái)存儲(chǔ)“ProductsCache”. 首先檢查MasterCacheKeyArray,如果其為null,用當(dāng)前date和time對(duì)其賦值。然后,創(chuàng)建一個(gè)從屬體。CacheDependency類的構(gòu)造器(constructor)可以有很多重載(overloads),本文使用的重載接受2個(gè)字符串?dāng)?shù)組作為輸入?yún)?shù)。第一個(gè)參數(shù)指定文件作為從屬體,但本文我們不大算用文件來(lái)做從屬體,所以我們將第一個(gè)輸入?yún)?shù)設(shè)為null;第二個(gè)參數(shù)指定cache keys作為從屬體,本文我們指定為MasterCacheKeyArray。然后將該CacheDependency傳遞給Insert方法。

對(duì)AddCacheItem(key, value)方法做了上述修改后,要使緩存失效,很簡(jiǎn)單,將從屬體移除即可:

[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Update, false)]
public bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
 bool result = API.UpdateProduct(productName, unitPrice, productID);

 // Invalidate the cache
 InvalidateCache();

 return result;
}

public void InvalidateCache()
{
 // Remove the cache dependency
 HttpRuntime.Cache.Remove(MasterCacheKeyArray[0]);
}

第五步:在表現(xiàn)層調(diào)用緩存層

  保存對(duì)ProductsCL類的修改,打開(kāi)Caching文件夾里的FromTheArchitecture.aspx頁(yè)面,并添加一個(gè)GridView控件。從GridView控件的智能標(biāo)簽里創(chuàng)建一個(gè)新的ObjectDataSource,在向?qū)У牡谝徊剑瑥南吕斜砝镞x擇ProductsCL,如下圖:


圖4:類ProductsCL包含在下拉列表里

  選定ProductsCL類后,點(diǎn)Next。我們可以看到在SELECT標(biāo)簽里有2個(gè)選項(xiàng):GetProducts() 和 GetProductsByCategoryID(categoryID)方法;而在UPDATE標(biāo)簽里只有唯一的一個(gè)UpdateProduct()方法。在SELECT標(biāo)簽里選擇GetProducts()方法;而在UPDATE標(biāo)簽里選擇那個(gè)唯一的UpdateProduct()方法,最后點(diǎn)Finish。


圖5:ProductsCL類的方法包含在下拉列表里。

  完成向?qū)Ш螅琕isual Studio會(huì)將ObjectDataSource的OldValuesParameterFormatString屬性設(shè)置為original_{0},并向GridView添加相應(yīng)的列。將OldValuesParameterFormatString該為默認(rèn)值{0}, 并啟用GridView控件的分頁(yè)、排序、編輯功能。由于緩存層CL的UploadProducts()方法只對(duì)產(chǎn)品的name 和 price進(jìn)行編輯,由此需要對(duì)GridView做相應(yīng)的修改以限制其只能編輯這2列。

  在前面的教程,我們指定GridView控件包含 ProductName, CategoryName,和UnitPrice3列。放心大膽的將其復(fù)制過(guò)來(lái),這樣,GridView 和 ObjectDataSource的聲明代碼看起來(lái)應(yīng)該像下面的這樣:

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: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") %>'>/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" 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="ProductsDataSource" 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è)擁?yè)面就使用了緩存層。為實(shí)地演示緩存,在ProductsCL類的GetProducts() 和 UpdateProduct()方法里設(shè)置斷點(diǎn)(breakpoints),在瀏覽器里訪問(wèn)該頁(yè)面,當(dāng)排序或分頁(yè)時(shí)就會(huì)執(zhí)行這些代碼,從內(nèi)存獲取數(shù)據(jù)。然后更新一條記錄,注意由于緩存失效,將從業(yè)務(wù)邏輯層BLL獲取數(shù)據(jù)并綁定到GridView。
注意:從本文download鏈接下載的緩存層并不完善。它只包含了一個(gè)ProductsCL類,它只包含幾個(gè)方法。此外,只有一個(gè)ASP.NET頁(yè)面(~/Caching/FromTheArchitecture.aspx)使用了緩存層CL,而其它的頁(yè)面都是直接調(diào)用業(yè)務(wù)邏輯層BLL。如果打算在你的應(yīng)用程序里使用緩存層CL,那么頁(yè)面層的所有調(diào)用都應(yīng)該先訪問(wèn)緩存層CL。

總結(jié):

  雖然可以在ASP.NET 2.0的表現(xiàn)層對(duì)SqlDataSource 和 ObjectDataSource控件實(shí)施緩存,但更理想的做法是在體系單獨(dú)分層來(lái)達(dá)到緩存的目的。在本文,我們?cè)诒憩F(xiàn)層和業(yè)務(wù)邏輯層之間創(chuàng)建了一個(gè)緩存層,該緩存層包含的類和方法與現(xiàn)有的業(yè)務(wù)邏輯層所包含的類和方法類似。當(dāng)然,也是在表現(xiàn)層調(diào)用。

  本示例及前面教程處理的是“觸發(fā)裝載”(reactive loading)—也就是說(shuō)當(dāng)發(fā)現(xiàn)請(qǐng)求的數(shù)據(jù)沒(méi)在內(nèi)存后將數(shù)據(jù)裝載進(jìn)內(nèi)存。其實(shí)數(shù)據(jù)也可以“預(yù)裝載”(proactively loaded)進(jìn)內(nèi)存—也就是說(shuō)在數(shù)據(jù)實(shí)際請(qǐng)求之前將其預(yù)先裝載進(jìn)內(nèi)存。在下一篇文章我們將看到預(yù)裝載的情形——在應(yīng)用程序啟動(dòng)的時(shí)候如何將靜態(tài)值(static values)裝載進(jìn)內(nèi)存。

  祝編程快樂(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ù)之五十八:在程序啟動(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ò)程
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六十七:在TableAdapters中使用JOINs

標(biāo)簽:聊城 慶陽(yáng) 海西 中衛(wèi) 臨夏 清遠(yuǎn) 甘肅

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)》,本文關(guān)鍵詞  在,ASP.NET,2.0,中,操作,數(shù)據(jù),;如發(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)文章
  • 下面列出與本文章《在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)》相關(guān)的同類信息!
  • 本頁(yè)收集關(guān)于在ASP.NET 2.0中操作數(shù)據(jù)之五十七:在分層架構(gòu)中緩存數(shù)據(jù)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    中文字幕1234区| 91精品国产乱码久久蜜臀| 欧美三级韩国三级日本一级| 亚洲精品国产精品久久清纯直播| 免费99精品国产自在在线| 国产成人av在线播放| 久久久久无码国产精品一区| 日韩国产精品毛片| 热久久精品免费视频| 成年人在线观看av| 女人十八岁毛片| 久久精品一区| 9久草视频在线视频精品| 亚洲午夜国产一区99re久久| 日韩欧美一区在线| 久久久久久久久久久久av| 高清一区二区三区视频| 中文字幕无码精品亚洲资源网久久| 亚洲欧美综合视频| 91浏览器在线观看| 视频在线观看一区| 国产精品网站一区| 在线播放91灌醉迷j高跟美女| 精品久久久av| 亚洲va码欧洲m码| 国产青草视频在线观看| 中文字幕第3页| 综合网在线观看| 美女视频黄免费的久久| 亚洲视频免费观看| 日韩视频一区二区三区| 国内精品久久久久久中文字幕 | 欧美制服第一页| 欧美日韩在线一区二区三区| 成人亚洲视频在线观看| 国产喷水在线观看| 亚洲精品久久久久久久久久| 久久女同精品一区二区| 欧美性淫爽ww久久久久无| 精品激情国产视频| 激情五月综合色婷婷一区二区| 日本三级免费观看| 亚洲伦理一区二区三区| 全部免费毛片在线播放一个| 国产女人18毛片水真多成人如厕| 欧美精品tushy高清| 久久久久国产一区二区三区| 欧美三日本三级少妇三99| 第四色婷婷基地| 久久久久久久久久综合| 全国精品久久少妇| 一区二区三区av电影| 国产丝袜精品第一页| 国产欧亚日韩视频| aa视频在线播放| 天堂网av2018| 欧性猛交ⅹxxx乱大交| 国产精品久久久久久久岛一牛影视 | 国产成人日日夜夜| 色国产精品一区在线观看| 久久国产精品久久久久久久久久| 久久av免费一区| 亚洲视频一二三四| 91精品国产综合久久久蜜臀九色 | 日韩精品一区二区三区老鸭窝| 日本a级片电影一区二区| 国产欧美自拍视频| 91激情视频在线观看| 欧美一区二区三区成人片在线| 亚洲日本成人在线观看| 亚洲天堂av网| 国产伦精品一区二区三区视频孕妇 | 91精品国产91久久久久久最新毛片| 欧美亚洲视频一区二区| 69精品丰满人妻无码视频a片| 免费视频91蜜桃| 亚洲 美腿 欧美 偷拍| 亚洲综合激情网| 中文字幕亚洲国产| 九九九九久久久久| 欧洲美女亚洲激情| 无码一区二区三区在线观看| www.亚洲国产| 日韩一二三四区| 国产主播精品在线| 北条麻妃在线观看| 国产一级av毛片| 国产乱一区二区| 精品视频1区2区3区| 青草成人免费视频| 国产一线二线三线女| 国产色无码精品视频国产| 五月天福利视频| 亚洲丝袜制服诱惑| 在线视频日本亚洲性| 精品一区二区三区视频日产| 91精产国品一二三| 国产视频第二页| 自拍偷拍欧美精品| 夜夜嗨av色一区二区不卡| 久久爱av电影| 捆绑裸体绳奴bdsm亚洲| 精品国产九九九| 尤物在线观看一区| 久久影院在线观看| 国产精品99久久久久久大便| 亚洲天堂岛国片| 日韩高清电影一区| 色老汉av一区二区三区| 青草成人免费视频| 日本精品www| 国产一区二区视频免费| 日本一区二区不卡视频| 精品国产一区二区国模嫣然| 成人av片网址| 国产高潮视频在线观看| 欧美特黄一级视频| 午夜精品久久久久影视| 91成人福利在线| 国产91在线视频观看| 性无码专区无码| 国产日韩欧美精品电影三级在线| 亚洲国产精品99| 久久综合中文色婷婷| 中国毛片在线观看| 秋霞午夜av一区二区三区 | 最新国产黄色网址| 国产精品人人爽| 亚洲大尺度视频在线观看| 久久免费视频这里只有精品| 国产午夜福利100集发布| 97久久久久久久| 国产欧美一区二区三区在线看蜜臀 | 精品久久一二三| 中文字幕精品三级久久久| 日本一区二区综合亚洲| 一区二区日韩精品| 亚洲 欧洲 日韩| 夫妻性生活毛片| 97久久久精品综合88久久| 亚洲一级黄色片| 亚洲一区二区在| 日韩黄色免费观看| 2020国产精品自拍| 中文亚洲视频在线| 日韩欧美视频免费在线观看| 日韩av一区二区在线播放| 日本一区二区免费在线| 久久天天躁狠狠躁夜夜躁| 中文字幕制服丝袜在线| 国产成人无码精品亚洲| 国产精品国产自产拍在线| 色综合天天狠天天透天天伊人| 国产毛片视频网站| 中文字幕av资源| 亚洲r级在线视频| 国产精品久久久久久婷婷天堂| 欧美人与性动交α欧美精品| 久久久亚洲人| 日韩一区二区高清| 欧美一区二区福利| 91杏吧porn蝌蚪| 久久精品一区二区三区四区| 久久不射热爱视频精品| 自拍日韩亚洲一区在线| 国产精品国产精品国产专区| 欧美视频在线看| 国产剧情久久久久久| 久久国产劲爆∧v内射| 美女国产一区二区| 亚洲经典中文字幕| 一区二区不卡在线视频 午夜欧美不卡'| 久久久久久久久久综合 | 中文字幕综合一区| 日韩国产一级片| 97人妻精品一区二区三区视频 | 国产黄色一级网站| 国产美女精品视频国产| 欧美亚一区二区| 国产呦系列欧美呦日韩呦| 中字幕一区二区三区乱码| 成年人国产精品| 久久亚洲精品一区二区| 亚洲精品高清无码视频| 涩涩视频免费看| 日韩精品在线一区二区| 亚洲欧洲精品一区| 狠狠人妻久久久久久综合| 亚欧色一区w666天堂| 国产成人久久精品| 素人fc2av清纯18岁| 99久久久无码国产精品| 欧美日韩国产成人| 在线视频一二区| 老司机精品视频在线| 亚洲性xxxx| 成人性生活视频免费看| 亚洲免费视频网| 欧美成人猛片aaaaaaa| 特级黄色录像片| 亚洲图片在线播放| 欧美日韩免费高清一区色橹橹 | 日本不卡视频一区| 国产乱码一区二区三区| 久久亚洲精品国产亚洲老地址| 国产精品久久久毛片| 青青草视频一区| 亚洲欧洲在线免费| 日韩黄色片视频| 亚洲国产精品久久久久久6q| 91精品国产综合久久蜜臀| 亚洲成年人专区| 国产一区二区三区成人| 91精品国产aⅴ一区二区| 日本久久高清视频| www.天堂av.com| 欧美v日韩v国产v| 日韩久久久久久久久久久久| 亚洲黄色在线播放| 亚洲第一区第一页| 亚洲 自拍 另类小说综合图区| 亚洲精品久久久蜜桃动漫 | 日韩视频永久免费观看| 中文字幕日韩综合| 国产麻豆精品在线观看| 九九九热精品免费视频观看网站| 亚洲天堂伊人网| 国精产品一区一区三区mba桃花| 另类专区欧美制服同性| 国产人妖在线观看| xf在线a精品一区二区视频网站| 2020国产精品视频| 国产又粗又猛又爽视频| 中文字幕一区在线| 国产日韩av高清| 免费成人深夜夜行网站| 亚洲永久免费视频| 狠狠爱一区二区三区| 日韩手机在线视频| 欧美日本乱大交xxxxx| 欧洲美女和动交zoz0z| 午夜久久久久久久久久| 日韩国产在线播放| 福利在线一区二区三区| 国产一区二区电影| 午夜精品一区二区三区视频免费看| 无码精品一区二区三区在线播放| 国产日韩欧美精品一区| www.成人av| 老熟妇仑乱一区二区av| 欧美日本韩国一区| 日本阿v视频在线观看| 久久综合图片| 久久精品影视伊人网| av电影中文字幕| 国产欧美日韩麻豆91| 7777奇米亚洲综合久久| 可以在线观看av的网站| 欧美日韩成人激情| 国产在线播放观看| 国产精品99久久久久久宅男| 欧美一区二区.| 精品国产国产综合精品| 欧美色播在线播放| 青青草原国产免费| 日韩专区在线视频| 欧美激情精品在线| 日本猛少妇色xxxxx免费网站| 亚洲国产美国国产综合一区二区| 色播五月综合| 欧美一级淫片免费视频魅影视频| 亚洲乱码一区av黑人高潮| 在线观看日本一区二区| 久久综合九色综合97婷婷| 成人两性免费视频| 精品人妻无码一区二区性色| 欧美成人r级一区二区三区| 国产精品免费成人| 成人sese在线| 成人国产在线视频| www.日韩一区| 日韩美女av在线| 久久黄色片网站| 国产欧美1区2区3区| 国产在线一区二区三区欧美| 国产女人18毛片水真多| 中文字幕精品在线| 一女三黑人理论片在线| 亚洲大片精品永久免费| 热久久最新地址| 美女视频黄 久久| 国产成人精品电影| 日韩欧美亚洲一区二区三区| 欧美日韩精品一区二区三区蜜桃| 国产精彩免费视频| 久久久综合视频| 九九九九精品九九九九| 人妻妺妺窝人体色www聚色窝| 久久国产精品久久久久久久久久| 国产第一页浮力| 9191久久久久久久久久久| 日本激情视频在线播放| 国产日韩视频一区二区三区| 欧美日韩综合久久| 日本不卡视频在线| 久久久亚洲天堂| 免费中文字幕在线观看| 欧美成人伊人久久综合网| 伊人成人222| 亚洲欧洲日产国产综合网| 日韩资源av在线| 日韩av电影免费观看高清完整版| 热99在线视频| 亚洲午夜18毛片在线看| 亚洲精品成人av| 极品白嫩的小少妇| 午夜精品一区二区三区免费视频 | 日本一区二区三级电影在线观看| 欧美精品一区二区视频| 日韩福利视频网| 国产精品欧美亚洲777777| 亚洲永久精品视频| 久久久国产精彩视频美女艺术照福利| 视频国产一区二区| 欧美一卡2卡三卡4卡5免费| 91大神免费观看| 婷婷久久综合九色综合绿巨人| 免费观看美女裸体网站| 91免费观看视频在线| 欧美精品一区二区三区在线四季| 人人狠狠综合久久亚洲| 91精品久久久久久久久久| 国产精品久久久久久无人区| 欧美美最猛性xxxxxx| 亚洲欧美一区二区三区四区五区| 日韩美女一区二区三区四区| 精品国产乱码久久久久久1区二区| 一区二区在线电影| 日本精品久久久久久久久久| 91蝌蚪国产九色| 日韩免费av一区二区三区| 国产麻豆成人精品| 国产日韩欧美一区二区三区四区| 亚洲色图21p| 国产欧美精品日韩| www.中文字幕| 国产成人小视频在线观看| 中文字幕第315页| 伦理中文字幕亚洲| 精品国产乱码一区二区| 久久精品国产成人| 日本在线观看中文字幕| 尤物精品国产第一福利三区 | 强制高潮抽搐sm调教高h| 日韩欧美高清一区| 精品久久久久久中文字幕人妻最新| 日本乱人伦一区| 国产精品天天av精麻传媒| 亚洲国产美女搞黄色| 国产成人精品无码播放| 亚洲精品第1页| 国产午夜伦鲁鲁| 国产日本欧美一区二区| 国产盗摄视频在线观看| 91丨porny丨中文| 午夜精品一区二区三区在线观看 | 美女视频一区在线观看| 国产成人看片| 蜜臀av亚洲一区中文字幕| 99国产在线视频| 美女视频黄免费的久久| 国内一区二区三区在线视频| 久久精品免费看| 精品免费日产一区一区三区免费| 国产一区二区0| 欧美一区国产一区| 成人禁用看黄a在线| 亚洲精品国产精品久久| 国产精品一区二区三区网站| 欧美在线3区| 99热99精品| 天堂av在线中文| 国产精品水嫩水嫩| 日本在线观看a| 大荫蒂欧美视频另类xxxx| 日本高清免费在线视频| 在线视频观看一区| 五月六月丁香婷婷| 777色狠狠一区二区三区| 亚洲精品成人无码| 日韩经典中文字幕| 岛国毛片在线观看| 欧美成人精品激情在线观看 | 一区二区欧美日韩视频| www日韩精品| 97精品一区二区视频在线观看| 国产精品久久久久久69| 国产精品久久久久久久久久东京| 男人天堂手机在线观看| 国产精品一区二区电影| 肉丝袜脚交视频一区二区| 国产在线精品一区| 成人av高清在线| 日本福利视频网站| 国产精品美女久久久久aⅴ国产馆| 欧美亚洲一二三区| 婷婷中文字幕综合| 亚洲av午夜精品一区二区三区| 日韩午夜在线播放| 成人自拍小视频|