Asp.net 2.0新增的缓存管理:
CacheDependency跟踪缓存依赖项,缓存依赖项可以是应用程序的 Cache 中的文件、目录或与其他对象的键。
SqlCacheDependency类在所有受支持的 SQL Server 版本 (7.0, 2000, 2005) 上监视特定的 SQL Server 数据库表,以便在该表发生更改时,自动从 Cache 中删除与该表关联的项。 数据库表发生更改时,将自动删除缓存项,并向 Cache 中添加新版本的项。在使用 SQL Server 2005 数据库时,SqlCacheDependency 类还支持与 System.Data.SqlClient.SqlDependency 类进行集成。使用 SQL Server 2005 的查询通知机制来检测使 SQL 查询结果无效的数据更改。与 SQL 查询关联的任何缓存项都将从 System.Web.Caching.Cache 中移除。在使用 SQL Server 2005 时,可以使用 SqlCacheDependency 类向应用程序的 Cache 添加依赖于 SQL Server 数据库表或 SQL 查询的项
AggregateCacheDependency类监视依赖项对象的集合,以便在任何依赖项对象更改时,该缓存项都会自动移除。数组中的对象可以是 CacheDependency对象、SqlCacheDependency 对象、从 CacheDependency派生的自定义对象或这些对象的任意组合.
AggregateCacheDependency类与 CacheDependency类的不同之处在于前者允许您将不同类型的多个依赖项与单个缓存项关联。例如,如果您创建一个从 SQL Server 数据库表和 XML 文件导入数据的页,则可创建一个 SqlCacheDependency对象来表示数据库表的依赖项,以及一个 CacheDependency来表XML 文件的依赖项。可创建 AggregateCacheDependency类的一个实例,将每个依赖项添加到该类中,而不是为每个依赖项调用 Cache.Insert 方法。然后,可使用单个Insert 调用使该页依赖于 AggregateCacheDependency实例。
举个例子说吧:
下面是为Petshop 4.0 中,product建立缓存依赖。下面是实现:
publicstatic IList
{
Product product =new Product();
if (!enableCaching)
return product.GetProductsByCategory(category);
string key ="product_by_category_"+ category;
IList
if (data ==null)
{
data = product.GetProductsByCategory(category);
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetProductDependency();
HttpRuntime.Cache.Add(key, data, cd, DateTime.Now.AddHours(productTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
}
return data;
}
引入Facade模式
在PetShop 4.0的设计中,是通过引入Facade模式以方便调用者更加简单地获得AggregateCacheDependency类型对象,引入Facade模式。
利用Facade模式可以将一些复杂的逻辑进行包装,以方便调用者对这些复杂逻辑的调用。就好像提供一个统一的门面一般,将内部的子系统封装起来,统一为一个高层次的接口。Facade模式的目的并非要引入一个新的功能,而是在现有功能的基础上提供一个更高层次的抽象,使得调用者可以直接调用,而不用关心内部的实现方式。以CacheDependency工厂为例,我们需要为调用者提供获得AggregateCacheDependency对象的简便方法,因而创建了DependencyFacade类:
publicstaticclass DependencyFacade {
privatestaticreadonlystring path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
publicstatic AggregateCacheDependency GetProductDependency()
{
if (!string.IsNullOrEmpty(path))
return DependencyAccess.CreateProductDependency().GetDependency();
else
returnnull;
}
}
DependencyFacade类封装了获取AggregateCacheDependency类型对象的逻辑,如此一来,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象:
AggregateCacheDependency dependency = DependencyFacade.GetCategoryDependency();
比起直接调用DependencyAccess类的GetDependency()方法而言,除了方法更简单之外,同时它还对CacheDependencyAssembly配置节进行了判断,如果其值为空,则返回null对象。
CacheDependency工厂
继承了抽象类TableDependency的Product、Category和Item类均需要在调用时创建各自的对象。由于它们的父类TableDependency实现了接口IPetShopCacheDependency,因而它们也间接实现了IPetShopCacheDependency接口,这为实现工厂模式提供了前提。在PetShop 4.0中,依然利用了配置文件和反射技术来实现工厂模式。命名空间PetShop.CacheDependencyFactory中,类DependencyAccess即为创建IPetShopCacheDependency对象的工厂类:
namespace PetShop.CacheDependencyFactory
{
publicstaticclass DependencyAccess
{
publicstatic IPetShopCacheDependency CreateProductDependency()
{
//创建PetShop.TableCacheDependency.Product实例,并把缓存依赖放入到AggregateCacheDependency中见TableDependency构造函数
return LoadInstance("Product");
}
//利用反射技术创建实体PetShop.TableCacheDependency.Product实例
privatestatic IPetShopCacheDependency LoadInstance(string className)
{
//
string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
string fullyQualifiedClass = path +"."+ className;
// Using the evidence given in the config file load the appropriate assembly and class
return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
}
}
}
构建Product CacheDepency
PetShop 4.0引入了SqlCacheDependency特性,对Category、Product和Item数据表对应的缓存实施了SQL Cache Invalidation技术。当对应的数据表数据发生更改后,该技术能够将相关项从缓存中移除。实现这一技术的核心是SqlCacheDependency类,它继承了CacheDependency类。然而为了保证整个架构的可扩展性,我们也允许设计者建立自定义的CacheDependency类,用以扩展缓存依赖。这就有必要为CacheDependency建立抽象接口,并在web.config文件中进行配置。
在PetShop 4.0的命名空间PetShop.ICacheDependency中,定义了名为IPetShopCacheDependency接口,它仅包含了一个接口方法
publicinterface IPetShopCacheDependency
{
{
AggregateCacheDependency GetDependency();
}
}
TableDependency的实现正是为Category、Product和Item数据表建立了对应的SqlCacheDependency类型的依赖项
publicabstractclass TableDependency : PetShop.ICacheDependency.IPetShopCacheDependency
{
// 获取表的分隔符
protectedchar[] configurationSeparator =newchar[] { ',' };
protected AggregateCacheDependency dependency =new AggregateCacheDependency();
protected TableDependency(string configKey) {
string dbName = ConfigurationManager.AppSettings["CacheDatabaseName"];//数据库名
string tableConfig = ConfigurationManager.AppSettings[configKey];
string[] tables = tableConfig.Split(configurationSeparator);
foreach (string tableName in tables)
dependency.Add(new SqlCacheDependency(dbName, tableName));
}
public AggregateCacheDependency GetDependency() {
return dependency;
}
}
/// Method to create an instance of Product dependency implementation
///创建Product实例,因为Product继承了TableDependency
根据各个数据表间的依赖关系,因而不同的数据表需要建立的依赖项也是不相同的,从配置文件中的value值可以看出。然而不管建立依赖项的多寡,其创建的行为逻辑都是相似的,因而在设计时,抽象了一个共同的类TableDependency,并通过建立带参数的构造函数,完成对依赖项的建立。由于接口方法GetDependency()的实现中,返回的对象dependency是在受保护的构造函数创建的,因此这里的实现方式也可以看作是Template Method模式的灵活运用。例如TableDependency的子类Product,就是利用父类的构造函数建立了Product、Category数据表的SqlCacheDependency依赖:
publicclass Product : TableDependency
{
public Product() : base("ProductTableDependency") { }
}
/*----------------------------------------------------------------------------------------------------------------*/