57在分层架构中缓存数据Word文档格式.docx
- 文档编号:18695649
- 上传时间:2022-12-31
- 格式:DOCX
- 页数:18
- 大小:77.12KB
57在分层架构中缓存数据Word文档格式.docx
《57在分层架构中缓存数据Word文档格式.docx》由会员分享,可在线阅读,更多相关《57在分层架构中缓存数据Word文档格式.docx(18页珍藏版)》请在冰豆网上搜索。
添加名为CL的文件夹和名为ProductsCL.cs的类
跟BLL里的ProductsBLL类一样,ProductsCL类应该包含相同的数据访问和修改方法。
不过在本文,我们只创建GetProducts()方法(在第3步)和GetProductsByCategoryID(categoryID)方法(在第4步)。
你可以在空闲的时候对ProductsCL类进行完善,并创建相应的CategoriesCL,EmployeesCL和SuppliersCL类
第二步:
对DataCache进行读和写
ObjectDataSource的缓存属性使用ASP.NETdatacache来存储从BLL获取的数据。
要访问datacache,可以从ASP.NET页面的code-behindclasses类或体系结构层(architecture)的类来访问。
要通过ASP.NET页面的code-behindclasses类对datacache进行读写,可使用如下模式:
?
1
2
//Readfromthecache(读)
objectvalue=Cache["
key"
];
3
4
5
//Addanewitemtothecache(写)
Cache["
]=value;
Cache.Insert(key,value);
Cache.Insert(key,value,CacheDependency);
Cache.Insert(key,value,CacheDependency,DateTime,TimeSpan);
Cacheclass类的Insert方法可以有很多的重载。
]=value和Cache.Insert(key,value)是相同的,都是向cache添加一个条目(item),不过没有指定expiry(可以理解为缓存持续时间)。
更具代表性的是,在我们向cache添加条目的时候指定一个expiry,它要么是dependency(从属体),要么是time-basedexpiry,又或者两者兼而有之,比如上面的最后2个表达式。
如果所需的数据存储在内存的话,首先调用缓存层的方法返回数据。
如果不在内存的话就调用BLL里相应的方法。
数据先缓存再返回。
就像下面的流程表解析的一样:
图3:
如果数据存在于内存的话就调用缓存层的方法。
上图的流程可用如下的模式:
6
7
Typeinstance=Cache["
]asType;
if(instance==null)
{
instance=BllMethodToGetInstance();
Cache.Insert(key,instance,...);
}
returninstance;
其中,Type是缓存在内存中的数据的类型——具体到本文,也就是Northwind.ProductsDataTable;
此外,key用于唯一地标识缓存的每一个条目。
如果指定了key值的那个条目不在内存中,那么instance就为null,然后用BLL类的某恰当的方法来检索数据,将获得的数据缓存到内存。
将instance返回后,它将包含一个对数据的引用(referencetothedata),数据要么来自内存,要么是BLL类的返回数据。
当访问内存时,请务必使用上述模式。
下面的这个模式,咋一看好像和上面的模式一模一样,但是有一个细微的区别,它存在一个racecondition(可以理解为不易察觉的隐式缺陷)。
racecondition很难调试,因为它只是偶尔发生,而且再次发生的可能性也小。
如下:
if(Cache["
]==null)
Cache.Insert(key,BllMethodToGetInstance(),...);
returnCache["
再一个就是,上述模式不是在局部变量里存储缓存条目的引用,而是在条件语句里直接访问数据,在return语句里直接返回数据。
设想这种情况,开始运行代码时Cache["
]是non-null的,但在运行return语句前,系统将其从内存里清除掉,那么代码就会返回一个null值,而不是我们期望的某种类型的对象。
注意:
如果仅仅是对datacache进行读或写访问,你没有必要进行同步访问(synchronizethreadaccess);
当然,如果你需要对内存里的数据进行多重操作(multipleoperations),你还是应该实施锁定(lock),或其它的机制。
如果要从datacache里清除某个条目,可以用Remove方法,比如:
Cache.Remove(key);
第三步:
从ProductsCL类返回产品信息
在本文,我们要在ProductsCL类里用2个方法来返回产品信息:
GetProducts()和GetProductsByCategoryID(categoryID).和业务逻辑层里的ProductsBL类相似,缓存层里的GetProducts()方法返回一个Northwind.ProductsDataTable对象,来获取所有产品的信息;
而GetProductsByCategoryID(categoryID)方法返回的是某个特定类别的所有产品。
如下的代码是ProductsCL类里的部分方法:
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
[System.ComponentModel.DataObject]
publicclassProductsCL
privateProductsBLL_productsAPI=null;
protectedProductsBLLAPI
get
if(_productsAPI==null)
_productsAPI=newProductsBLL();
return_productsAPI;
[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select,true)]
publicNorthwind.ProductsDataTableGetProducts()
conststringrawKey="
Products"
;
//Seeiftheitemisinthecache
Northwind.ProductsDataTableproducts=_
GetCacheItem(rawKey)asNorthwind.ProductsDataTable;
if(products==null)
//Itemnotfoundincache-retrieveitandinsertitintothecache
products=API.GetProducts();
AddCacheItem(rawKey,products);
returnproducts;
[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Select,false)]
publicNorthwind.ProductsDataTableGetProductsByCategoryID(intcategoryID)
if(categoryID<
0)
returnGetProducts();
else
stringrawKey=string.Concat("
ProductsByCategory-"
categoryID);
products=API.GetProductsByCategoryID(categoryID);
首先,注意运用到类(class)和方法(methods)上的属性DataObject和DataObjectMethodAttribute;
这些属性服务于ObjectDataSource的设置向导,指出那些类和方法应该出现在向导的设置步骤里。
因为ObjectDataSource控件要在表现层访问这些类和方法,所以我添加了这些属性,方便向导设置。
关于这些属性及其作用,请参阅本教程第2章《创建一个业务逻辑层》。
在GetProducts()和GetProductsByCategoryID(categoryID)方法里,GetCacheItem(key)返回的数据赋值给一个局部变量。
GetCacheItem(key)方法根据指定的key值在内存查找对应的缓存条目;
如果没找到,则用ProductsBLL类里相应的方法来检索数据,并用AddCacheItem(key,value)方法将获取的数据缓存到内存。
GetCacheItem(key)和AddCacheItem(key,value)方法分别对datacache进行读、写操作。
GetCacheItem(key)相对简单,它根据传入的key值,从Cache类返回数据,如下:
privateobjectGetCacheItem(stringrawKey)
returnHttpRuntime.Cache[GetCacheKey(rawKey)];
privatereadonlystring[]MasterCacheKeyArray={"
ProductsCache"
};
privatestringGetCacheKey(stringcacheKey)
returnstring.Concat(MasterCacheKeyArray[0],"
-"
cacheKey);
GetCacheItem(key)并没有直接使用我们提供的key值,而是调用GetCacheKey(key)方法,因为该方法根据“ProductsCache-”返回key;
在上述代码中,MasterCacheKeyArray用于存储字符串“ProductsCache”。
当然,AddCacheItem(key,value)方法也会用到MasterCacheKeyArray,我们稍后会看到。
在ASP.NET页面后台代码类(code-behindclass),我们可以使用Page类的Cache属性来访问datacache,就像我们在第2步里的表达式:
]=value一样;
而在体系结构的类(注:
具体到本文,就是缓存层类(ProductsCL),我们可以通过2种方式来访问:
HttpRuntime.Cache或HttpContext.Current.Cache;
在PeterJohnson的博客里有一篇文章《HttpRuntime.Cachevs.HttpContext.Current.Cache》(
注意:
如果你是使用的类库工程(ClassLibraryprojects),一定要记得引用System.Web才能使用HttpRuntime和HttpContext类。
如果没有在内存找到数据,ProductsCL类将从业务逻辑层BLL获取数据,并使用AddCacheItem(key,value)对数据进行缓存,可以用下面的代码向内存添加缓存数据,其缓存时间为60秒:
constdoubleCacheDuration=60.0;
privatevoidAddCacheItem(stringrawKey,objectvalue)
HttpRuntime.Cache.Insert(GetCacheKey(rawKey),value,null,
DateTime.Now.AddSeconds(CacheDuration),Caching.Cache.NoSlidingExpiration);
其中,DateTime.Now.AddSeconds(CacheDuration)指定了缓存时间—60秒;
而System.Web.Caching.Cache.NoSlidingExpiration指明了不存在可变缓存时间(noslidingexpiration).虽然Insert()方法可以包含绝对时间和可变时间(absoluteandslidingexpiry)2种定义缓存时间的输入参数,但是你只能指定其中一个,如果你同时指定绝对时间和可变时间2个参数的话,Insert()方法会抛出一ArgumentException异常。
直接执行AddCacheItem(key,value)方法会有一些弊端,我们将在第4步解释并修正。
第4步:
当数据被修改时使缓存失效
除了数据检索方法外,缓存层还应该包含插入、更新、删除数据的方法。
缓存层的数据修改方法并不是修改缓存的数据,而是调用业务逻辑层的相应方法,然后使缓存数据失效。
就像前面章节探讨的那样,当激活ObjectDataSource的缓存属性时,便可调用它的Insert,Update或Delete方法。
下面的UpdateProduct方法,说明了如何在缓存层CL执行数据修改方法:
[System.ComponentModel.DataObjectMethodAttribute(DataObjectMethodType.Update,false)]
publicboolUpdateProduct(stringproductName,decimal?
unitPrice,intproductID)
boolresult=API.UpdateProduct(productName,unitPrice,productID);
//TODO:
Invalidatethecache
returnresult;
在业务逻辑层的方法返回数据以前,我们需要将缓存的数据失效。
不过,这并非易事,无论ProductsCLclass'
sGetProducts()还是GetProductsByCategoryID(categoryID)都会向内存添加条目,并且GetProductsByCategoryID(categoryID)方法会为每种类别添加几个条目(因为每种类别有几种甚至更多的产品)。
要使缓存数据失效,我们需要将ProductsCL类添加的所有条目删除。
为此,在AddCacheItem(key,value)方法里,当添加条目时为其指定一个缓存从属体(cachedependency)。
一般来说,缓存从属体可以是内存里的另一个条目;
文件系统里的一个文件;
又或者是MicrosoftSQLServerdatabase数据库里的数据。
当从属体发生改变,或者从内存里移除时,其对应的缓存条目会自动的从内存删除。
在本教程,当ProductsCL类向内存添加条目时,我们创建一个额外的条目作为其从属体。
由此,要删除缓存条目,仅仅移除这些从属体即可。
我们来更改AddCacheItem(key,value)方法,当用该方法向内存添加缓存数据时,使每个条目与一个从属体(cachedependency)对应起来。
System.Web.Caching.CacheDataCache=HttpRuntime.Cache;
//MakesureMasterCacheKeyArray[0]isinthecache-ifnot,addit
if(DataCache[MasterCacheKeyArray[0]]==null)
DataCache[MasterCacheKeyArray[0]]=DateTime.Now;
//AddaCacheDependency
System.Web.Caching.CacheDependencydependency=
newCacheDependency(null,MasterCacheKeyArray);
DataCache.Insert(GetCacheKey(rawKey),value,dependency,
DateTime.Now.AddSeconds(CacheDuration),
System.Web.Caching.Cache.NoSlidingExpiration);
MasterCacheKeyArray是一个字符串数组,用来存储“ProductsCache”.首先检查MasterCacheKeyArray,如果其为null,用当前date和time对其赋值。
然后,创建一个从属体。
CacheDependency类的构造器(constructor)可以有很多重载(overloads),本文使用的重载接受2个字符串数组作为输入参数。
第一个参数指定文件作为从属体,但本文我们不大算用文件来做从属体,所以我们将第一个输入参数设为null;
第二个参数指定cachekeys作为从属体,本文我们指定为MasterCacheKeyArray。
然后将该CacheDependency传递给Insert方法。
对AddCacheItem(key,value)方法做了上述修改后,要使缓存失效,很简单,将从属体移除即可:
//Invalidatethecache
InvalidateCache();
publicvoidInvalidateCache()
//Removethecachedependency
HttpRuntime.Cache.Remove(MasterCacheKeyArray[0]);
第五步:
在表现层调用缓存层
保存对ProductsCL类的修改,打开Caching文件夹里的FromTheArchitecture.aspx页面,并添加一个GridView控件。
从GridView控件的智能标签里创建一个新的ObjectDataSource,在向导的第一步,从下拉列表里选择ProductsCL,如下图:
图
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 57 分层 架构 缓存 数据