• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

PetShop之ASP.NET缓存--two

原作者: [db:作者] 来自: [db:来源] 收藏 邀请
在PetShop 4.0的命名空间PetShop.ICacheDependency中,定义了名为IPetShopCacheDependency接口,它仅包含了一个接口方法:
  public interface IPetShopCacheDependency
  {
   AggregateCacheDependency GetDependency();
  }
  
  AggregateCacheDependency是.Net Framework 2.0新增的一个类,它负责监视依赖项对象的集合。当这个集合中的任意一个依赖项对象发生改变时,该依赖项对象对应的缓存对象都将被自动移除。
  AggregateCacheDependency类起到了组合CacheDependency对象的作用,它可以将多个 CacheDependency对象甚至于不同类型的CacheDependency对象与缓存项建立关联。由于PetShop需要为Category、 Product和Item数据表建立依赖项,因而IPetShopCacheDependency的接口方法GetDependency()其目的就是返 回建立了这些依赖项的AggregateCacheDependency对象。
  
  4.3.2 CacheDependency实现
  
  CacheDependency的实现正是为Category、Product和Item数据表建立了对应的SqlCacheDependency类型的依赖项,如代码所示:
  public abstract class TableDependency : IPetShopCacheDependency
  {
   // This is the separator that’s used in web.config
   protected char[] configurationSeparator = new char[] { ‘,’ };
  
   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;
   }
  }
  
  需要建立依赖项的数据库与数据表都配置在web.config文件中,其设置如下:
  
  根据各个数据表间的依赖关系,因而不同的数据表需要建立的依赖项也是不相同的,从配置文件中的value值可以看出。然而不管建立依赖项的多 寡,其创建的行为逻辑都是相似的,因而在设计时,抽象了一个共同的类TableDependency,并通过建立带参数的构造函数,完成对依赖项的建立。 由于接口方法GetDependency()的实现中,返回的对象dependency是在受保护的构造函数创建的,因此这里的实现方式也可以看作是 Template Method模式的灵活运用。例如TableDependency的子类Product,就是利用父类的构造函数建立了Product、Category 数据表的SqlCacheDependency依赖:
  public class Product : TableDependency
  {
   public Product() : base(”ProductTableDependency”) { }
  }
  
  如果需要自定义CacheDependency,那么创建依赖项的方式又有不同。然而不管是创建SqlCacheDependency对象, 还是自定义的CacheDependency对象,都是将这些依赖项添加到AggregateCacheDependency类中,因而我们也可以为自定 义CacheDependency建立专门的类,只要实现IPetShopCacheDependency接口即可。
  
  4.3.3 CacheDependency工厂
  
  继承了抽象类TableDependency的Product、Category和Item类均需要在调用时创建各自的对象。由于它们的父类 TableDependency实现了接口IPetShopCacheDependency,因而它们也间接实现了 IPetShopCacheDependency接口,这为实现工厂模式提供了前提。
  
  在PetShop 4.0中,依然利用了配置文件和反射技术来实现工厂模式。命名空间PetShop.CacheDependencyFactory中,类DependencyAccess即为创建IPetShopCacheDependency对象的工厂类:
  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);
   }
  }
  整个工厂模式的实现如图4-3所示:
  
  
   图4-3 CacheDependency工厂
  
  虽然DependencyAccess类创建了实现了IPetShopCacheDependency接口的类Category、 Product、Item,然而我们之所以引入IPetShopCacheDependency接口,其目的就在于获得创建了依赖项的 AggregateCacheDependency类型的对象。我们可以调用对象的接口方法GetDependency(),如下所示:
  AggregateCacheDependency dependency = DependencyAccess.CreateCategoryDependency().GetDependency();
  
  为了方便调用者,似乎我们可以对DependencyAccess类进行改进,将原有的CreateCategoryDependency()方法,修改为创建AggregateCacheDependency类型对象的方法。
  
  然而这样的做法扰乱了作为工厂类的DependencyAccess的本身职责,且创建IPetShopCacheDependency接口对象的行为仍然有可能被调用者调用,所以保留原有的DependencyAccess类仍然是有必要的。
  
  在PetShop 4.0的设计中,是通过引入Facade模式以方便调用者更加简单地获得AggregateCacheDependency类型对象。
  
  4.3.4 引入Facade模式
  
  利用Facade模式可以将一些复杂的逻辑进行包装,以方便调用者对这些复杂逻辑的调用。就好像提供一个统一的门面一般,将内部的子系统封装起来,统一为一个高层次的接口。一个典型的Facade模式示意图如下所示:
  
  
  图4-4 Facade模式
  
  Facade模式的目的并非要引入一个新的功能,而是在现有功能的基础上提供一个更高层次的抽象,使得调用者可以直接调用,而不用关心内部的 实现方式。以CacheDependency工厂为例,我们需要为调用者提供获得AggregateCacheDependency对象的简便方法,因而 创建了DependencyFacade类:
  public static class DependencyFacade
  {
   private static readonly string path = ConfigurationManager.AppSettings[”CacheDependencyAssembly”];
   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;
   }
  }
  
  DependencyFacade类封装了获取AggregateCacheDependency类型对象的逻辑,如此一来,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象:
  AggregateCacheDependency dependency = DependencyFacade.GetCategoryDependency();
  
  比起直接调用DependencyAccess类的GetDependency()方法而言,除了方法更简单之外,同时它还对CacheDependencyAssembly配置节进行了判断,如果其值为空,则返回null对象。
  
  在PetShop.Web的App_Code文件夹下,静态类WebUtility的GetCategoryName()和GetProductName()方法调用了DependencyFacade类。例如GetCategoryName()方法:
  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)
   {
   // 通过web.config的配置获取duration值;
   int cacheDuration = int.Parse(ConfigurationManager.AppSettings[”CategoryCacheDuration”]);
   // 如果缓存中不存在该数据项,则通过业务逻辑层访问数据库获取;
   data = category.GetCategory(categoryId).Name;
   // 通过Facade类创建AggregateCacheDependency对象;
   AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();
   // 将数据项以及AggregateCacheDependency 对象存储到缓存中;
   HttpRuntime.Cache.Add(cacheKey, data, cd, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
   }
   return data;
  }
  
  GetCategoryName()方法首先会检查缓存中是否已经存在CategoryName数据项,如果已经存在,就通过缓存直接获取数 据;否则将通过业务逻辑层调用数据访问层访问数据库获得CategoryName,在获得了CategoryName后,会将新获取的数据连同 DependencyFacade类创建的AggregateCacheDependency对象添加到缓存中。
  
  WebUtility静态类被表示层的许多页面所调用,例如Product页面:
  public partial class Products : System.Web.UI.Page
  {
   protected void Page_Load(object sender, EventArgs e)
   {
   Page.Title = WebUtility.GetCategoryName(Request.QueryString[”categoryId”]);
   }
  }
  
  显示页面title的逻辑是放在Page_Load事件方法中,因而每次打开该页面都要执行获取CategoryName的方法。如果没有采用缓存机制,当Category数据较多时,页面的显示就会非常缓慢。
  
  4.3.5 引入Proxy模式
  
  业务逻辑层BLL中与Product、Category、Item有关的业务方法,其实现逻辑是调用数据访问层(DAL)对象访问数据库,以 获取相关数据。为了改善系统性能,我们就需要为这些实现方法增加缓存机制的逻辑。当我们操作增加了缓存机制的业务对象时,对于调用者而言,应与BLL业务 对象的调用保持一致。也即是说,我们需要引入一个新的对象去控制原来的BLL业务对象,这个新的对象就是Proxy模式中的代理对象。

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
asp.net缓存发布时间:2022-07-10
下一篇:
asp.net2.0下如何配置使用fckeditor发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap