现在的位置: 首页 > 综合 > 正文

SqlCacheDependency缓存应用

2012年01月10日 ⁄ 综合 ⁄ 共 6410字 ⁄ 字号 评论关闭

aspnet_regsql工具位于Windows\Microsoft.NET\Framework\[版本文件夹下]
按指定顺序直接操作

dos命令

启动数据库缓存依赖项
执行:aspnet_regsql -S dev -U 用户名 -P 密码 -d 缓存数据库名称 -ed
检查数据库生成表:AspNet_SqlCacheTablesForChangeNotification

启动对数据库中某个表的缓存依赖项
执行:aspnet_regsql -S dev -U 用户名 -P 密码 -d 缓存数据库名称 -t 数据表名称 -et
检查数据库表:AspNet_SqlCacheTablesForChangeNotification生成一条记录

-?  显示该工具的帮助功能;
-S  后接的参数为数据库服务器的名称或者IP地址;
-U  后接的参数为数据库的登陆用户名;
-P  后接的参数为数据库的登陆密码;
-E  当使用windows集成验证时,使用该功能;
-d  后接参数为对哪一个数据库采用SqlCacheDependency功能;
-t  后接参数为对哪一个表采用SqlCacheDependency功能;
-ed  允许对数据库使用SqlCacheDependency功能;
-dd  禁止对数据库采用SqlCacheDependency功能;
-et  允许对数据表采用SqlCacheDependency功能;
-dt  禁止对数据表采用SqlCacheDependency功能;
-lt  列出当前数据库中有哪些表已经采用sqlcachedependency功能。

3.为ASP.NET提供查询追踪的数据表的情况,同时还将为使用了 SqlCacheDependency的表添加触发器,分别对应Insert、Update、Delete等与数据更改相关的操作。例如Product数 据表的触发器:
Create TRIGGER dbo.[Product_AspNet_SqlCacheNotification_Trigger] ON [数据表名称]
    FOR Insert, Update, Delete AS BEGIN
    SET NOCOUNT ON
    EXEC dbo.AspNet_SqlCacheUpdateChangeIdStoredProcedure N'数据表名称'
END

4.定义缓存工厂接口:
public interface IsnsShopCacheDependency
{     
    AggregateCacheDependency GetDependency();
}
AggregateCacheDependency是.Net Framework 2.0新增的一个类,它负责监视依赖项对象的集合。当这个集合中的任意一个依赖项对象发生改变时,该依赖项对象对应的缓存对象都将被自动移除。
AggregateCacheDependency 类起到了组合CacheDependency对象的作用,它可以将多个CacheDependency对象甚至于不同类型的CacheDependency对象与缓存项建立关联。IsnsShopCacheDependency的接口

方法GetDependency()其目的就是返回建立了这些依赖项的 AggregateCacheDependency对象。

5.CacheDependency实现
CacheDependency的实现正是为test数据表建立了对应的SqlCacheDependency类型的依赖项,如代码所示:
public abstract class TableDependency : IPetShopCacheDependency
{
    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;
    }
}

6.需要建立依赖项的数据库与数据表都配置在web.config文件中,其设置如下:
<add key="CacheDatabaseName" value="sns"/>
<add key="testTableDependency" value="test"/>

<!--启用数据缓存-->
    <add key="EnableCaching" value="true"/>
    <!--DependencyFacade.cs 缓存依赖项选项CONFIG_CACHE_ASSEMBLY-->
    <add key="CacheDependencyAssembly" value="TableCacheDependency"/>
    <!--缓存时间hour-->
    <add key="UserCacheDuration" value="12"/>
    <!--首页中间经历经验,缓存事件minute-->
    <add key="ExpCacheDuration" value="10"/>
    <!--缓存数据库的名称-->
    <add key="CacheDatabaseName" value="databasename"/>
    <!--用半角逗号分隔的每个实例TableDependency列出表的依赖-->
    <add key="testTableDependency" value="test"/>
  </appSettings>
  <system.web>
    <!--定义缓存策略:-->
    <caching>
      <sqlCacheDependency enabled="true">
        <databases>
          <add connectionStringName="DBsqlConnectionString" name="databasename"/>
        </databases>
</sqlCacheDependency>   

 

7.根据各个数据表间的依赖关系,因而不同的数据表需要建立的依赖项也是不相同的,从配置文件中的value值可以看出。然而不管建立依赖项的多寡,其 创建的行为逻辑都是相似的,因而在设计时,

抽象了一个共同的类TableDependency,并通过建立带参数的构造函数,完成对依赖项的建立。由于接 口方法GetDependency()的实现中,返回的对象dependency是在受保护的构造函数创建的,因此这里

的实现方式也可以看作是 Template Method模式的灵活运用。例如TableDependency的子类test,就是利用父类的构造函数建立了test数据表的SqlCacheDependency依赖:
public class test: TableDependency
{
    public test() : base("testTableDependency") { }
}
如果需要自定义CacheDependency,那么创建依赖项的方式又有不同。然而不管是创建SqlCacheDependency对象,还是自 定义的CacheDependency对象,都是将这些依赖项添加到

AggregateCacheDependency类中,因而我们也可以为自定义 CacheDependency建立专门的类,只要实现IsnsCacheDependency接口即可。

8.CacheDependency工厂
继承了抽象类TableDependency的test类均需要在调用时创建各自的对象。由于它们的父类 TableDependency实现了接口IsnsShopCacheDependency,因而它们也间接实现了 IsnsCacheDependency接口,

这为实现工厂模式提供了前提。依然利用了配置文件和反射技术来实现工厂模式。命名空间CacheDependencyFactory中,类DependencyAccess即为创建IsnsCacheDependency对象的工厂类:
public static class DependencyAccess
{          
    public static IPetShopCacheDependency CreateItemDependency()
    {
        return LoadInstance("test");
    }
    private static IPetShopCacheDependency LoadInstance(string className)
    {
        string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
        string fullyQualifiedClass = path + "." + className;
        return (IPetShopCacheDependency)Assembly.Load(path).CreateInstance(fullyQualifiedClass);
    }
}

9.虽然DependencyAccess类创建了实现了IsnsCacheDependency接口的类test,然而我们之所以引入IsnsCacheDependency接口,其目的就在于获得创建了依赖项的 AggregateCacheDependency类型的对象

。我们可以调用对象的接口方法GetDependency(),AggregateCacheDependency dependency = DependencyAccess.CreatetestDependency().GetDependency();为了方便调用者,似乎我们可以对

DependencyAccess类进行改进,将原有的CreatetestDependency()方法,修改为创建AggregateCacheDependency类型对象的方法。然而这样的做法扰乱了作为工厂类的DependencyAccess的本身职责,且

创建IsnsCacheDependency接口对象的行为仍然有可能被调用者调用,所以保留原有的DependencyAccess类仍然是有必要的。通过引入Facade模式以方便调用者更加简单地获得AggregateCacheDependency

类型对象。

10.引入Facade模式
利用Facade模式可以将一些复杂的逻辑进行包装,以方便调用者对这些复杂逻辑的调用。就好像提供一个统一的门面一般,将内部的子系统封装起来,统一为一个高层次的接口。
Facade模式的目的并非要引入一个新的功能,而是在现有功能的基础上提供一个更高层次的抽象,使得调用者可以直接调用,而不用关心内部的实现方 式。以CacheDependency工厂为例,我们需要为调

用者提供获得AggregateCacheDependency对象的简便方法,因而创建了 DependencyFacade类:
public static class DependencyFacade
{
    private static readonly string path = ConfigurationManager.AppSettings["CacheDependencyAssembly"];
    public static AggregateCacheDependency GettestDependency()
    {
        if (!string.IsNullOrEmpty(path))
            return DependencyAccess.CreatetesDependency().GetDependency();
        else
            return null;
    }
}
DependencyFacade类封装了获取AggregateCacheDependency类型对象的逻辑,如此一来,调用者可以调用相关方法获得创建相关依赖项的AggregateCacheDependency类型对象:
AggregateCacheDependency dependency = DependencyFacade.GetCategoryDependency();
比起直接调用DependencyAccess类的GetDependency()方法而言,除了方法更简单之外,同时它还对CacheDependencyAssembly配置节进行了判断,如果其值为空,则返回null对象。

11.业务逻辑层实现对缓存依赖的调用

private static readonly int expTimeout = int.Parse(ConfigurationManager.AppSettings["testCacheDuration"]);   //超时时间
private static readonly bool enableCaching = bool.Parse(ConfigurationManager.AppSettings["EnableCaching"]); //启用缓存

if (!enableCaching)
            {
                return expvew.GetRandomExperience(topCount);
            }
            string key = "exp_index";
            IList<Exp_experience> expdata = (IList<Exp_experience>)HttpRuntime.Cache[key];
            if (expdata == null)
            {
                expdata = (IList<Exp_experience>)expvew.GetRandomExperience(topCount);
                AggregateCacheDependency cd = DependencyFacade.GetExpDependency();
                HttpRuntime.Cache.Add(key, expdata, cd, DateTime.Now.AddMinutes(expTimeout), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
            }
            return expdata;

 

参考:petshop4.0分档分享第四章
 

抱歉!评论已关闭.