.net中Petshop4.0 缓存设计学习教程

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<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];
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)
{
//<add key="CacheDependencyAssembly" value="PetShop.TableCacheDependency"/>配置文件获取程序集名称+className创建CacheDependency实例
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
{
// 获取表的分隔符<add key="ProductTableDependency" value="Product,Category"/>
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") { }  
}

/*----------------------------------------------------------------------------------------------------------------*/

时间: 2024-08-02 12:30:09

.net中Petshop4.0 缓存设计学习教程的相关文章

C++编程中的数据类型和常量学习教程_C 语言

C++数据类型计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数.浮点数.字符等形式).不同的数据之间往往还存在某些联系(例如由若干个整数组成一个整数数组).数据结构指的是数据的组织形式.例如,数组就是一种数据结构.不同的计算机语言所允许使用的数据结构是不同的.处理同一类问题,如果数据结构不同,算法也会不同.例如,对10个整数排序和对包含10个元素的整型数组排序的算法是不同的. C++的数据包括常量与变量,常量与变量都具有类型.由以上这些数据类型还可以构成更复杂的数据结构.例如利用

jQuery中的基本选择器用法学习教程_jquery

一.简单选择器在使用jQuery 选择器时,必须使用"$()"函数来包装CSS 规则.而CSS 规则作为参数传递到jQuery 对象内部后,再返回包含页面中对应元素的jQuery 对象.随后,就可以对这个获取到的DOM 节点进行行为操作了. #box {//使用ID 选择器的CSS 规则 color:red;//将ID 为box 的元素字体颜色变红 } 在jQuery 选择器里,我们使用如下的方式获取同样的结果: $('#box').css('color', 'red');//获取DO

Java线程编程中Thread类的基础学习教程_java

一.线程的状态 在正式学习Thread类中的具体方法之前,我们先来了解一下线程有哪些状态,这个将会有助于后面对Thread类中的方法的理解. 线程从创建到最终的消亡,要经历若干个状态.一般来说,线程包括以下这几个状态:创建(new).就绪(runnable).运行(running).阻塞(blocked).time waiting.waiting.消亡(dead). 当需要新起一个线程来执行某个子任务时,就创建了一个线程.但是线程创建之后,不会立即进入就绪状态,因为线程的运行需要一些条件(比如内

缓存设计学习笔记

背景 最近在< redis 开发与运维>这是在看11章时候记得笔记 存在和合理性 缓存到处都是啊 先放个最简单的图, 这里面每一层都可以有缓存 client 缓存 最常见的浏览器的http缓存. 还有app一般也加缓存,比如陌陌,这么大活跃的情况下,不缓存服务端鸭梨太大,"更多帧"的菜单就是客户端缓存了的,每15分钟才会去刷新一次 web server 最常见的nginx 对不常更新的静态资源可以在location 段里配expire来设置缓存时间: 还有nginx作为反向

MySQL中事务概念的简洁学习教程_Mysql

事务是由一步或几步数据库操作序列组成逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行.程序和事务是两个不同的概念.一般而言:一段程序中可能包含多个事务. 事务具有四个特性:原子性(Atomicity).一致性(Consistency).隔离性(Isolation)和持续性(Durability).这四个特性也简称ACID性. 1)原子性:事务是应用中最小的执行单位,就如原子是自然界最小颗粒,具有不可再分的特征一样.事务是应用中不可再分的最小逻辑执行体. 2)一致性:事务执行的结果,必须使数

MySQL中的事件调度基础学习教程_Mysql

经常需要有一些定时任务在MySQL表上执行,例如统计.迁移.删除无用数据等.之前的作法是利用Linux cron定时运行脚本,但是发现这样的额外依赖有时并不方便,例如单机多实例部署时,就需要分别手动分别配置不同的cron任务,需要额外配置相应的用户和权限:新环境部署时容易遗漏cron任务等. MySQL提供了Event Scheduler,与Linux下的crontab类似,可以根据时间调度来运行任务,运行一次或多次. 完整的Event Schduler创建语句如下: CREATE [DEFIN

Java中的数组基础知识学习教程_java

数字 通常情况下,当我们处理数字时,使用原始数据类型,如 byte,int,long,double 等. 示例 int i = 5000; float gpa = 13.65; byte mask = 0xaf; 然而,在开发中,我们会遇到需要使用对象而不是原始数据类型的情况.为了实现这个, Java 为每个原始数据类型提供包装类. 所有的包装类 (Integer, Long, Byte, Double, Float, Short) 是抽象类 Number 的子类. 这种包装是由编译器处理,这个

完全掌握C++编程中构造函数使用的超级学习教程_C 语言

构造函数是一种可初始化其类的实例的成员函数.构造函数具有与类相同的名称,没有返回值.构造函数可以具有任意数量的参数,类可以具有任意数量的重载构造函数.构造函数可以具有任何可访问性(公共.受保护或私有).如果未定义任何构造函数,则编译器会生成不采用任何参数的默认构造函数:可以通过将默认构造函数声明为已删除来重写此行为.构造函数顺序构造函数按此顺序执行工作: 按声明顺序调用基类和成员构造函数. 如果类派生自虚拟基类,则会将对象的虚拟基指针初始化. 如果类具有或继承了虚函数,则会将对象的虚函数指针初始

C++编程中new运算符的使用学习教程_C 语言

new运算符用作从自由存储为 type-name 的对象或对象数组分配内存,并将已适当分类的非零指针返回到对象. [::] new [placement] new-type-name [new-initializer] [::] new [placement] ( type-name ) [new-initializer] 备注如果不成功,则 new 将返回零或引发异常:有关详细信息,请参阅 new 和 delete 运算符. 通过编写自定义异常处理例程并调用 _set_new_handler