ASP.NET的缓存机制
2016-07-05 11:12
489 查看
Asp.NET提供了2中缓存机制来提供缓存功能:
应用程序缓存:允许开发者将程序生成的数据或报表业务对象放入缓存中。
页输出缓存:可以直接从中获取存放在缓存中的页面,而不需要经过繁杂的对该页面的再次处理。
1.应用程序缓存:
是通过ASP.NET来管理内存中的缓存空间,放入缓存中的对象以键值对的方式存储,这便于用户在访问缓存中的数据项时,可以根据key值判断该项是否存在缓存中。
放入在缓存中的数据对象,其生命周期是受限制的,即使在整个应用程序的生命周期内,也不能保证该数据对象一直有效。此外,调用者还可以通过CachItemRemovedCallback委托定义回调方法使得数据项被移除时能够通知用户。
在.NET Framwork中,应用程序缓存通过System.Web.Caching.Cache类实现,对于每一个应用程序域,都要创建一个cache类的实例,其生命周期与应用程序的生命周期保持一致,可以用Add或insert方法将数据项添加到应用程序缓存中,Cache["first"]="First Item"; Cache.Insert("Second","Second Item");还可以为应用程序缓存添加依赖项,使得当依赖项发生更改时,该数据项能够从缓存中移除:
string[] dependencies ={"second"};
Cache.Insert("Third","Third Item",new CacheDependency(null,dependencies));
可以手动移除相关数据项:Cache.Remove("second");
2.页输出缓存:
可以通过内存将处理后的ASP.NET页面存储起来,当客户端再一次访问该页面时,可以省去页面的处理过程,从而提高页面访问的性能,以及Web服务器的吞吐量。
页输出缓存分为整页缓存和部分缓存,可以通过@OutputCache指令完成对Web页面的输出缓存:<%@OutputCache Duration"60" VaryByParam="none">设置缓存时间60s,只要没有超过设置的期限值,当用户访问相同的页面或空间时,就可以直接在缓存中获取。
VaryByParam参数可以根据设置的参数值建立不同的缓存,如在一个输出天气预报结果的页面中,如果需要为一个ID为txtCiry的textbox控件建立缓存,其值显示某城市的气温,则可如下设置:<%@OutputCache Duration"60" VaryByParam="txtCity"%>,asp.net会对txtCity控件的值进行判断,只有输入的值与缓存值相同才会从缓存中取出数据。
引入缓存可以极大提高应用程序的性能,当缓存机制也有缺点,就是数据过期的问题,一旦应用程序数据或页面结果值发生变化,则再缓存有效期范围内获取的结果将是过期的不准确的数据。.NET2.0引入了自定义缓存依赖项,特别是基于MS-SQL Server的SqlCacheDependency 特性,使得我们可以避免数据过期的问题,它能够根据数据库中相应数据的变化,通知缓存,并移除那些过期的数据。
3.SqlCacheDependency特性:
监视特定的数据库表,并创建依赖于该表以及表中数据行的依赖项,当数据表或表中特定行的数据发生更改时,具有依赖项的数据项就会失效,并自动从Cache中删除,从而保证了缓存中不再保留过期数据.
SQL SERVER 2005及以上完全支持SqlDependency特性,SQL SERVER7.0及2000不支持。配置SQL server以支持SqlCacheDependency特性:aspnet_regsql命令行工具或使用SqlCacheDenpendencyAdmin类:
3.1.使用aspnet_regsql:
aspnet_regsql工具位于C:\Windows\Microsoft.NET\Framework64\v4.0.30319中,使用cmd命令行转到该目录,并执行命令:aspnet_regsql -S localhost -E -d 数据库名 -ed 为数据库启用sqlCacheDependency特性。
执行命令:aspnet_regsql -S localhost -E -t 表名 -et 为某个表启用sqlCacheDependency特性。
此时会在数据库中建立一个名为AspNet_SqlCacheTablesForChangeNotification的表,同时添加了一组存储过程并为启用了SqlCacheDependency特性的表创建了触发器。
命令参数说明:
3.2.利用SqlCacheDependencyAdmin类:
3.3.SqlCacheDependency特性在APS.NET应用程序中的实现:
3.3.1.为了可扩展性,首先建立ICacheDependency类库,在其中建立IPetShopCacheDependency接口:
[csharp]
view plain
copy
print?
public interface IPetShopCacheDependency {
AggregateCacheDependency GetDependency();
}
AggregateCacheDependency类起到了组合CacheDependency对象的作用,他可以将多个CacheDependency对象甚至不同类型的CacheDependency对象与缓存项建立关联。
3.3.2实现ICacheDependency:
即为数据库表建立对应的SqlCahcedependency依赖项。首先建立TableCacheDependency类库,在其中建立TableDependency类
[csharp]
view plain
copy
print?
public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency {
protected char[] configurationSeparator = new char[] { ',' };
protected AggregateCacheDependency dependency = new AggregateCacheDependency();
protected TableDependency(string configKey) {
string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"];//要建立SqlCacheDependency依赖项的数据库名
string tableConfig = ConfigurationManager.AppSettings[configKey];//要建立SqlCacheDependency依赖项的数据库表名
string[] tables = tableConfig.Split(configurationSeparator);
foreach (string tableName in tables)
dependency.Add(new SqlCacheDependency(dbName, tableName));//为数据库表建立对应的SqlCahcedependency依赖项并加入到AggregateCacheDependency的监视中
}
public AggregateCacheDependency GetDependency() {
return dependency;
}
}
[html]
view plain
copy
print?
<add key="CacheDatabaseName" value="MSPetShop4"/>
<add key="CategoryTableDependency" value="Category"/>
<add key="ProductTableDependency" value="Product,Category"/>
<add key="ItemTableDependency" value="Product,Category,Item"/>
根据各个数据表之间的依赖关系,因而不同的数据表需要建立的依赖项也是不同的。
然后为各个启用了SqlCacheDependency特性的数据表建立实体对象并继承TableDependency:
<pre name="code" class="csharp">public class Category : TableDependency {
/// <summary>
/// Call its base constructor by passing its specific configuration key
/// </summary>
public Category() : base("CategoryTableDependency") { }
}
<pre name="code" class="html"> 3.3.3.创建CacheDependncy抽象工厂:
由于TableDependency类的派生类(即启用了sqlcachedependency特性的数据表对于的实体)均需要在被调用时创建各自的对象,故可使用工厂模式;
首先创建CacheDependencyFactory类库,创建DependencyAccess类:为每个启用了sqlcachedependency特性的数据表对于的实体提供创建实例的方法:
<pre name="code" class="csharp"> public static class DependencyAccess {
public static IPetShopCacheDependency CreateCategoryDependency() {
return LoadInstance("Category");
}
public static IPetShopCacheDependency CreateProductDependency() {
return LoadInstance("Product");
}
public static IPetShopCacheDependency CreateItemDependency() {
return LoadInstance("Item");
}
private static IPetShopCacheDependency LoadInstance(string className) {
string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
string fullyQualifiedClass = path + "." + className;
return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
}
}
虽然DependencyAccess类创建了实现IPetShopCaheDependency接口的类Category\Item\Product,然而我们之所以引入接口IPetShopCaheDependency
,其目的就在于<strong>为每个实体获得创建了依赖项的AggregateCacheDependency</strong>。可以通过<strong>Facade模式</strong>来获取。
3.3.4.Facade模式:
利用Facade模式可以将一些复杂的逻辑进行包装,以方便调用者对这些复杂逻辑的调用,就好像提供了一个统一的门面一般,将内部的子系统封装起来,统一为一个高层次的接口。
Facade模式的引入并非要引入一个新的功能,而是在现有功能的基础上提供一个更高层次的抽象,使得调用者可以直接调用,而不用关心内部的实现形式。
在CacheDependencyFactory类库中创建DependencyFacade类:
[html]
view plain
copy
print?
<pre name="code" class="csharp"> public static class DependencyFacade {
private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];//PetShop.TableCacheDependency
public static AggregateCacheDependency GetCategoryDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateCategoryDependency().GetDependency();
else
return null;
}
public static AggregateCacheDependency GetProductDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateProductDependency().GetDependency();
else
return null;
}
public static AggregateCacheDependency GetItemDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateItemDependency().GetDependency();
else
return null;
}
}
<pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="csharp">DependencyFacade封装了获取AggregateCacheDependency的方法,这样,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象
AggregateCacheDependency denpendency = DependencyFacade.GetCategoryDependency();
调用:
[csharp]
view plain
copy
print?
public static string GetCategoryName(string categoryId) {
Category category = new Category();
if (!enableCaching)
return category.GetCategory(categoryId).Name;
string cacheKey = string.Format(CATEGORY_NAME_KEY, categoryId);
string data = (string)HttpRuntime.Cache[cacheKey];
if (data == null) {
int cacheDuration = int.Parse(ConfigurationManager.AppSettings["CategoryCacheDuration"]);
data = category.GetCategory(categoryId).Name;
<strong> AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();</strong>
//Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(cacheKey, data, <strong>cd</strong>, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
BLL业务逻辑层中与Category,Item等实体有关的业务方法,其实现逻辑是调用DAL层对象访问数据库,以获取相关数据,为了给这些方法增加缓存机制的逻辑,需要引入一个新的对象去控制原来的BLL业务对象,该对象中的方法与BLL业务对象中的方法一样,只是从缓存中获取数据,而不访问DAL层,这个对象就是Proxy模式中的代理对象。
在Web中的APP_Code文件夹中建立ProductDataProxy类作为BLL业务层的业务对象Product的代理对象,并在其方法中使用缓存机制:
[csharp]
view plain
copy
print?
public static class ProductDataProxy {
private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings["ProductCacheDuration"]);
private static readonly bool enableCaching = bool.Parse(ConfigurationManager.AppSettings["EnableCaching"]);
/// <summary>
/// This method acts as a proxy between the web and BLL to check whether the
/// underlying data has already been cached.
/// </summary>
/// <param name="category">Category</param>
/// <returns>List of ProductInfo from Cache or Business component</returns>
public static IList<ProductInfo> GetProductsByCategory(string category) {
Product product = new Product();
if (!enableCaching)
return product.GetProductsByCategory(category);
string key = "product_by_category_" + category;
IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProductsByCategory(category);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
/// <summary>
/// This method acts as a proxy between the web and BLL to check whether the
/// underlying search result has already been cached.
/// </summary>
/// <param name="text">Search Text</param>
/// <returns>List of ProductInfo from Cache or Business component</returns>
public static IList<ProductInfo> GetProductsBySearch(string text) {
Product product = new Product();
if (!enableCaching)
return product.GetProductsBySearch(text);
string key = "product_search_" + text;
IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProductsBySearch(text);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
/// <summary>
/// This method acts as a proxy between the web and business components to check whether the
/// underlying product has already been cached.
/// </summary>
/// <param name="productId">Product Id</param>
/// <returns>ProductInfo from Cache or Business component</returns>
public static ProductInfo GetProduct(string productId) {
Product product = new Product();
if (!enableCaching)
return product.GetProduct(productId);
string key = "product_" + productId;
ProductInfo data = (ProductInfo)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProduct(productId);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
}
为页面输出缓存设置缓存依赖项SqlCacheDependency:
[csharp]
view plain
copy
print?
this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
Asp.NET提供了2中缓存机制来提供缓存功能:
应用程序缓存:允许开发者将程序生成的数据或报表业务对象放入缓存中。
页输出缓存:可以直接从中获取存放在缓存中的页面,而不需要经过繁杂的对该页面的再次处理。
1.应用程序缓存:
是通过ASP.NET来管理内存中的缓存空间,放入缓存中的对象以键值对的方式存储,这便于用户在访问缓存中的数据项时,可以根据key值判断该项是否存在缓存中。
放入在缓存中的数据对象,其生命周期是受限制的,即使在整个应用程序的生命周期内,也不能保证该数据对象一直有效。此外,调用者还可以通过CachItemRemovedCallback委托定义回调方法使得数据项被移除时能够通知用户。
在.NET Framwork中,应用程序缓存通过System.Web.Caching.Cache类实现,对于每一个应用程序域,都要创建一个cache类的实例,其生命周期与应用程序的生命周期保持一致,可以用Add或insert方法将数据项添加到应用程序缓存中,Cache["first"]="First Item"; Cache.Insert("Second","Second Item");还可以为应用程序缓存添加依赖项,使得当依赖项发生更改时,该数据项能够从缓存中移除:
string[] dependencies ={"second"};
Cache.Insert("Third","Third Item",new CacheDependency(null,dependencies));
可以手动移除相关数据项:Cache.Remove("second");
2.页输出缓存:
可以通过内存将处理后的ASP.NET页面存储起来,当客户端再一次访问该页面时,可以省去页面的处理过程,从而提高页面访问的性能,以及Web服务器的吞吐量。
页输出缓存分为整页缓存和部分缓存,可以通过@OutputCache指令完成对Web页面的输出缓存:<%@OutputCache Duration"60" VaryByParam="none">设置缓存时间60s,只要没有超过设置的期限值,当用户访问相同的页面或空间时,就可以直接在缓存中获取。
VaryByParam参数可以根据设置的参数值建立不同的缓存,如在一个输出天气预报结果的页面中,如果需要为一个ID为txtCiry的textbox控件建立缓存,其值显示某城市的气温,则可如下设置:<%@OutputCache Duration"60" VaryByParam="txtCity"%>,asp.net会对txtCity控件的值进行判断,只有输入的值与缓存值相同才会从缓存中取出数据。
引入缓存可以极大提高应用程序的性能,当缓存机制也有缺点,就是数据过期的问题,一旦应用程序数据或页面结果值发生变化,则再缓存有效期范围内获取的结果将是过期的不准确的数据。.NET2.0引入了自定义缓存依赖项,特别是基于MS-SQL Server的SqlCacheDependency 特性,使得我们可以避免数据过期的问题,它能够根据数据库中相应数据的变化,通知缓存,并移除那些过期的数据。
3.SqlCacheDependency特性:
监视特定的数据库表,并创建依赖于该表以及表中数据行的依赖项,当数据表或表中特定行的数据发生更改时,具有依赖项的数据项就会失效,并自动从Cache中删除,从而保证了缓存中不再保留过期数据.
SQL SERVER 2005及以上完全支持SqlDependency特性,SQL SERVER7.0及2000不支持。配置SQL server以支持SqlCacheDependency特性:aspnet_regsql命令行工具或使用SqlCacheDenpendencyAdmin类:
3.1.使用aspnet_regsql:
aspnet_regsql工具位于C:\Windows\Microsoft.NET\Framework64\v4.0.30319中,使用cmd命令行转到该目录,并执行命令:aspnet_regsql -S localhost -E -d 数据库名 -ed 为数据库启用sqlCacheDependency特性。
执行命令:aspnet_regsql -S localhost -E -t 表名 -et 为某个表启用sqlCacheDependency特性。
此时会在数据库中建立一个名为AspNet_SqlCacheTablesForChangeNotification的表,同时添加了一组存储过程并为启用了SqlCacheDependency特性的表创建了触发器。
命令参数说明:
3.2.利用SqlCacheDependencyAdmin类:
3.3.SqlCacheDependency特性在APS.NET应用程序中的实现:
3.3.1.为了可扩展性,首先建立ICacheDependency类库,在其中建立IPetShopCacheDependency接口:
[csharp]
view plain
copy
print?
public interface IPetShopCacheDependency {
AggregateCacheDependency GetDependency();
}
public interface IPetShopCacheDependency { AggregateCacheDependency GetDependency(); }AggregateCacheDependency 类负责监视依赖项对象的集合(即启用了SqlCachedependency特性的那些数据库表),当这个集合中的任意一个依赖项对象发生变化时,该依赖项对象对应的被依赖的缓存对象都将被自动移除。
AggregateCacheDependency类起到了组合CacheDependency对象的作用,他可以将多个CacheDependency对象甚至不同类型的CacheDependency对象与缓存项建立关联。
3.3.2实现ICacheDependency:
即为数据库表建立对应的SqlCahcedependency依赖项。首先建立TableCacheDependency类库,在其中建立TableDependency类
[csharp]
view plain
copy
print?
public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency {
protected char[] configurationSeparator = new char[] { ',' };
protected AggregateCacheDependency dependency = new AggregateCacheDependency();
protected TableDependency(string configKey) {
string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"];//要建立SqlCacheDependency依赖项的数据库名
string tableConfig = ConfigurationManager.AppSettings[configKey];//要建立SqlCacheDependency依赖项的数据库表名
string[] tables = tableConfig.Split(configurationSeparator);
foreach (string tableName in tables)
dependency.Add(new SqlCacheDependency(dbName, tableName));//为数据库表建立对应的SqlCahcedependency依赖项并加入到AggregateCacheDependency的监视中
}
public AggregateCacheDependency GetDependency() {
return dependency;
}
}
public abstract class TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency { protected char[] configurationSeparator = new char[] { ',' }; protected AggregateCacheDependency dependency = new AggregateCacheDependency(); protected TableDependency(string configKey) { string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"];//要建立SqlCacheDependency依赖项的数据库名 string tableConfig = ConfigurationManager.AppSettings[configKey];//要建立SqlCacheDependency依赖项的数据库表名 string[] tables = tableConfig.Split(configurationSeparator); foreach (string tableName in tables) dependency.Add(new SqlCacheDependency(dbName, tableName));//为数据库表建立对应的SqlCahcedependency依赖项并加入到AggregateCacheDependency的监视中 } public AggregateCacheDependency GetDependency() { return dependency; } }需要建立依赖项的数据库与数据库表都配置在web.config中:
[html]
view plain
copy
print?
<add key="CacheDatabaseName" value="MSPetShop4"/>
<add key="CategoryTableDependency" value="Category"/>
<add key="ProductTableDependency" value="Product,Category"/>
<add key="ItemTableDependency" value="Product,Category,Item"/>
根据各个数据表之间的依赖关系,因而不同的数据表需要建立的依赖项也是不同的。
然后为各个启用了SqlCacheDependency特性的数据表建立实体对象并继承TableDependency:
<pre name="code" class="csharp">public class Category : TableDependency {
/// <summary>
/// Call its base constructor by passing its specific configuration key
/// </summary>
public Category() : base("CategoryTableDependency") { }
}
<pre name="code" class="html"> 3.3.3.创建CacheDependncy抽象工厂:
由于TableDependency类的派生类(即启用了sqlcachedependency特性的数据表对于的实体)均需要在被调用时创建各自的对象,故可使用工厂模式;
首先创建CacheDependencyFactory类库,创建DependencyAccess类:为每个启用了sqlcachedependency特性的数据表对于的实体提供创建实例的方法:
<pre name="code" class="csharp"> public static class DependencyAccess {
public static IPetShopCacheDependency CreateCategoryDependency() {
return LoadInstance("Category");
}
public static IPetShopCacheDependency CreateProductDependency() {
return LoadInstance("Product");
}
public static IPetShopCacheDependency CreateItemDependency() {
return LoadInstance("Item");
}
private static IPetShopCacheDependency LoadInstance(string className) {
string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
string fullyQualifiedClass = path + "." + className;
return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
}
}
虽然DependencyAccess类创建了实现IPetShopCaheDependency接口的类Category\Item\Product,然而我们之所以引入接口IPetShopCaheDependency
,其目的就在于<strong>为每个实体获得创建了依赖项的AggregateCacheDependency</strong>。可以通过<strong>Facade模式</strong>来获取。
<add key="CacheDatabaseName" value="MSPetShop4"/> <add key="CategoryTableDependency" value="Category"/> <add key="ProductTableDependency" value="Product,Category"/> <add key="ItemTableDependency" value="Product,Category,Item"/> 根据各个数据表之间的依赖关系,因而不同的数据表需要建立的依赖项也是不同的。 然后为各个启用了SqlCacheDependency特性的数据表建立实体对象并继承TableDependency: <pre name="code" class="csharp">public class Category : TableDependency { /// <summary> /// Call its base constructor by passing its specific configuration key /// </summary> public Category() : base("CategoryTableDependency") { } } <pre name="code" class="html"> 3.3.3.创建CacheDependncy抽象工厂: 由于TableDependency类的派生类(即启用了sqlcachedependency特性的数据表对于的实体)均需要在被调用时创建各自的对象,故可使用工厂模式; 首先创建CacheDependencyFactory类库,创建DependencyAccess类:为每个启用了sqlcachedependency特性的数据表对于的实体提供创建实例的方法: <pre name="code" class="csharp"> public static class DependencyAccess { public static IPetShopCacheDependency CreateCategoryDependency() { return LoadInstance("Category"); } public static IPetShopCacheDependency CreateProductDependency() { return LoadInstance("Product"); } public static IPetShopCacheDependency CreateItemDependency() { return LoadInstance("Item"); } private static IPetShopCacheDependency LoadInstance(string className) { string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"]; string fullyQualifiedClass = path + "." + className; return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass); } } 虽然DependencyAccess类创建了实现IPetShopCaheDependency接口的类Category\Item\Product,然而我们之所以引入接口IPetShopCaheDependency ,其目的就在于<strong>为每个实体获得创建了依赖项的AggregateCacheDependency</strong>。可以通过<strong>Facade模式</strong>来获取。
3.3.4.Facade模式:
利用Facade模式可以将一些复杂的逻辑进行包装,以方便调用者对这些复杂逻辑的调用,就好像提供了一个统一的门面一般,将内部的子系统封装起来,统一为一个高层次的接口。
Facade模式的引入并非要引入一个新的功能,而是在现有功能的基础上提供一个更高层次的抽象,使得调用者可以直接调用,而不用关心内部的实现形式。
在CacheDependencyFactory类库中创建DependencyFacade类:
[html]
view plain
copy
print?
<pre name="code" class="csharp"> public static class DependencyFacade {
private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];//PetShop.TableCacheDependency
public static AggregateCacheDependency GetCategoryDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateCategoryDependency().GetDependency();
else
return null;
}
public static AggregateCacheDependency GetProductDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateProductDependency().GetDependency();
else
return null;
}
public static AggregateCacheDependency GetItemDependency() {
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateItemDependency().GetDependency();
else
return null;
}
}
<pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="csharp">DependencyFacade封装了获取AggregateCacheDependency的方法,这样,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象
AggregateCacheDependency denpendency = DependencyFacade.GetCategoryDependency();
<pre name="code" class="csharp"> public static class DependencyFacade { private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];//PetShop.TableCacheDependency public static AggregateCacheDependency GetCategoryDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateCategoryDependency().GetDependency(); else return null; } public static AggregateCacheDependency GetProductDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateProductDependency().GetDependency(); else return null; } public static AggregateCacheDependency GetItemDependency() { if (!string.IsNullOrEmpty(path)) return DependencyAccess.CreateItemDependency().GetDependency(); else return null; } } <pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="html"><pre name="code" class="csharp"><pre name="code" class="csharp">DependencyFacade封装了获取AggregateCacheDependency的方法,这样,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象 AggregateCacheDependency denpendency = DependencyFacade.GetCategoryDependency();
调用:
[csharp]
view plain
copy
print?
public static string GetCategoryName(string categoryId) {
Category category = new Category();
if (!enableCaching)
return category.GetCategory(categoryId).Name;
string cacheKey = string.Format(CATEGORY_NAME_KEY, categoryId);
string data = (string)HttpRuntime.Cache[cacheKey];
if (data == null) {
int cacheDuration = int.Parse(ConfigurationManager.AppSettings["CategoryCacheDuration"]);
data = category.GetCategory(categoryId).Name;
<strong> AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();</strong>
//Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(cacheKey, data, <strong>cd</strong>, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
public static string GetCategoryName(string categoryId) { Category category = new Category(); if (!enableCaching) return category.GetCategory(categoryId).Name; string cacheKey = string.Format(CATEGORY_NAME_KEY, categoryId); string data = (string)HttpRuntime.Cache[cacheKey]; if (data == null) { int cacheDuration = int.Parse(ConfigurationManager.AppSettings["CategoryCacheDuration"]); data = category.GetCategory(categoryId).Name; <strong> AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();</strong> //Store the output in the data cache, and Add the necessary AggregateCacheDependency object HttpRuntime.Cache.Add(cacheKey, data, <strong>cd</strong>, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } return data; }3.3.5.引入Proxy模式:
BLL业务逻辑层中与Category,Item等实体有关的业务方法,其实现逻辑是调用DAL层对象访问数据库,以获取相关数据,为了给这些方法增加缓存机制的逻辑,需要引入一个新的对象去控制原来的BLL业务对象,该对象中的方法与BLL业务对象中的方法一样,只是从缓存中获取数据,而不访问DAL层,这个对象就是Proxy模式中的代理对象。
在Web中的APP_Code文件夹中建立ProductDataProxy类作为BLL业务层的业务对象Product的代理对象,并在其方法中使用缓存机制:
[csharp]
view plain
copy
print?
public static class ProductDataProxy {
private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings["ProductCacheDuration"]);
private static readonly bool enableCaching = bool.Parse(ConfigurationManager.AppSettings["EnableCaching"]);
/// <summary>
/// This method acts as a proxy between the web and BLL to check whether the
/// underlying data has already been cached.
/// </summary>
/// <param name="category">Category</param>
/// <returns>List of ProductInfo from Cache or Business component</returns>
public static IList<ProductInfo> GetProductsByCategory(string category) {
Product product = new Product();
if (!enableCaching)
return product.GetProductsByCategory(category);
string key = "product_by_category_" + category;
IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProductsByCategory(category);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
/// <summary>
/// This method acts as a proxy between the web and BLL to check whether the
/// underlying search result has already been cached.
/// </summary>
/// <param name="text">Search Text</param>
/// <returns>List of ProductInfo from Cache or Business component</returns>
public static IList<ProductInfo> GetProductsBySearch(string text) {
Product product = new Product();
if (!enableCaching)
return product.GetProductsBySearch(text);
string key = "product_search_" + text;
IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProductsBySearch(text);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
/// <summary>
/// This method acts as a proxy between the web and business components to check whether the
/// underlying product has already been cached.
/// </summary>
/// <param name="productId">Product Id</param>
/// <returns>ProductInfo from Cache or Business component</returns>
public static ProductInfo GetProduct(string productId) {
Product product = new Product();
if (!enableCaching)
return product.GetProduct(productId);
string key = "product_" + productId;
ProductInfo data = (ProductInfo)HttpRuntime.Cache[key];
// Check if the data exists in the data cache
if (data == null) {
// If the data is not in the cache then fetch the data from the business logic tier
data = product.GetProduct(productId);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
}
public static class ProductDataProxy { private static readonly int productTimeout = int.Parse(ConfigurationManager.AppSettings["ProductCacheDuration"]); private static readonly bool enableCaching = bool.Parse(ConfigurationManager.AppSettings["EnableCaching"]); /// <summary> /// This method acts as a proxy between the web and BLL to check whether the /// underlying data has already been cached. /// </summary> /// <param name="category">Category</param> /// <returns>List of ProductInfo from Cache or Business component</returns> public static IList<ProductInfo> GetProductsByCategory(string category) { Product product = new Product(); if (!enableCaching) return product.GetProductsByCategory(category); string key = "product_by_category_" + category; IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key]; // Check if the data exists in the data cache if (data == null) { // If the data is not in the cache then fetch the data from the business logic tier data = product.GetProductsByCategory(category); // Create a AggregateCacheDependency object from the factory AggregateCacheDependency cd = DependencyFacade.GetProductDependency(); // Store the output in the data cache, and Add the necessary AggregateCacheDependency object HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } return data; } /// <summary> /// This method acts as a proxy between the web and BLL to check whether the /// underlying search result has already been cached. /// </summary> /// <param name="text">Search Text</param> /// <returns>List of ProductInfo from Cache or Business component</returns> public static IList<ProductInfo> GetProductsBySearch(string text) { Product product = new Product(); if (!enableCaching) return product.GetProductsBySearch(text); string key = "product_search_" + text; IList<ProductInfo> data = (IList<ProductInfo>)HttpRuntime.Cache[key]; // Check if the data exists in the data cache if (data == null) { // If the data is not in the cache then fetch the data from the business logic tier data = product.GetProductsBySearch(text); // Create a AggregateCacheDependency object from the factory AggregateCacheDependency cd = DependencyFacade.GetProductDependency(); // Store the output in the data cache, and Add the necessary AggregateCacheDependency object HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } return data; } /// <summary> /// This method acts as a proxy between the web and business components to check whether the /// underlying product has already been cached. /// </summary> /// <param name="productId">Product Id</param> /// <returns>ProductInfo from Cache or Business component</returns> public static ProductInfo GetProduct(string productId) { Product product = new Product(); if (!enableCaching) return product.GetProduct(productId); string key = "product_" + productId; ProductInfo data = (ProductInfo)HttpRuntime.Cache[key]; // Check if the data exists in the data cache if (data == null) { // If the data is not in the cache then fetch the data from the business logic tier data = product.GetProduct(productId); // Create a AggregateCacheDependency object from the factory AggregateCacheDependency cd = DependencyFacade.GetProductDependency(); // Store the output in the data cache, and Add the necessary AggregateCacheDependency object HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null); } return data; } }与BLL层的Product.cs中的GetProductsByCategory()方法相比,增加了缓存机制,当缓存内不存在相关数据项时,则直接调用业务逻辑层BLL中Product的GetProductsByCategory()方法,并将其与对应的AggregateCacheDependency 对象一起存储在缓存中。
为页面输出缓存设置缓存依赖项SqlCacheDependency:
[csharp]
view plain
copy
print?
this.CachePolicy.Dependency = DependencyFacade.GetProductDependency();
相关文章推荐
- Android AOP 之AspectJ(一)
- asp.net Core开启全新的时代,用视频来告诉你,学习就是这么SO easy。
- 『ExtJS』表单(二)表单行为与Asp.NET页面的消息回复
- TimesTen 数据库复制学习:11. ASP带缓存组复制的几种固定架构模式
- asp:Repeater数据源为空时处理方式
- 在ASP.NET MVC中,使用Bundle来打包压缩js和css(转)
- ASP.NET-----验证控件
- ASP.NET MVC4企业级实战目录
- ASP.NET MVC4企业级实战目录
- 【iReport+JasperReport】3.在Java工程中用jasper导出Excel报表
- ASP.net DbGeography
- ASP.net如何保证EF操作类线程内唯一
- 树莓派无法上网
- asp.net Calendar 控件
- asp.net ImageButton 控件
- asp.net LinkButton 控件
- asp.net core 之静态文件目录的操作
- [Spring框架]Spring AOP基础入门总结二:Spring基于AspectJ的AOP的开发.
- asp.net WebService的一个简单示例
- asp.net mvc 生成条形码