找回密码
 立即注册
首页 业界区 业界 NH剖析:Configuration篇——SessionFactory的Cache之la ...

NH剖析:Configuration篇——SessionFactory的Cache之lambda-configuration配置

谷江雪 2025-5-29 15:06:47
本节内容
       
  • 系列引入       
  • 概览       
  • 实体缓存配置       
  • 实体缓存配置(Weak Type)       
  • 实体缓存配置(EntityCache)
                     
    • EntityCache原理               
    • EntityCache使用
                   
  • 结语       
  • 参考资料
系列引入

NHibernate3.0剖析系列分别从Configuration篇、Mapping篇、Query篇、Session策略篇、应用篇等方面全面揭示NHibernate3.0新特性和应用及其各种应用程序的集成,基于NHibernte3.0版本。如果你还不熟悉NHibernate,可以快速阅读NHibernate之旅系列文章导航系列入门,如果你已经在用NHibernate了,那么请跟上NHibernate3.0剖析系列吧。
           
  • NHibernate专题:http://kb.cnblogs.com/zt/nhibernate/       
  • NHibernate官方站点:http://nhforge.org/       
  • NHibernate参考文档:http://nhforge.org/doc/nh/en/       
  • 获取NHibernate地址:http://sourceforge.net/projects/nhibernate/
概览

在上一篇文章中我们介绍了lambda表达式配置(lambda-configuration),其中还剩下EntityCache扩展方法用于配置Domain的二级缓存。
实体缓存配置

曾经,Fabio Maulo做过一次调查,发现几乎没有人在hibernate.cfg.xml或者app.config文件中配置二级缓存,发现通常做法是在各个Domain的映射(Mapping)文件中使用配置。我想其中的一个原因是大家还不知道有这个功能。不过在介绍EntityCache扩展方法之前,我们还是先回顾下NH2弱类型(Weak Type)的缓存配置吧。
实体缓存配置(Weak Type)

在hibernate.cfg.xml文件中在session-factory-configuration节点里通过设置class-cache和collection-cache节点配置实体缓存和集合缓存:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
复制代码
这样NHibernate通过扫描hibernate.cfg.xml文件,然后调用Configuration类中的方法来实现缓存配置,所以我们只有手动编写“字符串信息”没法使用强类型。
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>public Configuration SetCacheConcurrencyStrategy(String clazz, String concurrencyStrategy)public void SetCacheConcurrencyStrategy(String clazz, String concurrencyStrategy, String region)public Configuration SetCollectionCacheConcurrencyStrategy(string collectionRole, string concurrencyStrategy)
复制代码
在各个Domain的Mapping文件中,我们在class或者集合(set、bag、list、map)节点配置二级缓存:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
复制代码
实体缓存配置(EntityCache)

EntityCache原理

所谓EntityCache配置就是通过lambda表达式来实现的,即在ConfigurationExtensions类中EntityCache扩展方法,我们看看这个扩展方法具体实现吧:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>public static Configuration EntityCache(this Configuration configuration,     Action entityCacheConfiguration)    where TEntity : class{    var ecc = new EntityCacheConfigurationProperties();    entityCacheConfiguration(ecc);    if (ecc.Strategy.HasValue)    {        configuration.SetCacheConcurrencyStrategy(typeof(TEntity).FullName,             EntityCacheUsageParser.ToString(ecc.Strategy.Value),ecc.RegionName);    }    foreach (var collection in ecc.Collections)    {        configuration.SetCollectionCacheConcurrencyStrategy(collection.Key,            EntityCacheUsageParser.ToString(collection.Value.Strategy),collection.Value.RegionName);    }    return configuration;}
复制代码
我们一看便知,就是调用Configuration类中的SetCacheConcurrencyStrategy和SetCollectionCacheConcurrencyStrategy方法实现的。
EntityCache使用

我们为Domain配置二级缓存,首先定义一个Domain实体,这个实体中也包含了一个集合:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>public class EntityToCache{    public string Name { get; set; }    public IList Elements { get; set; }}
复制代码
我们使用EntityCache扩展方法实践一下吧:
1.只配置Domain实体二级缓存:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>configure.EntityCache(ce =>      {          ce.Strategy = EntityCacheUsage.NonStrictReadWrite;          ce.RegionName = "MyRegion";      });
复制代码
2.配置Domain实体和它的集合二级缓存:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>configure.EntityCache(ce =>         {             ce.Strategy = EntityCacheUsage.NonStrictReadWrite;             ce.RegionName = "MyRegion";             ce.Collection(e => e.Elements, cc =>                       {                           cc.RegionName = "MyCollectionRegion";                           cc.Strategy = EntityCacheUsage.NonStrictReadWrite;                       });         });
复制代码
3.只配置集合(不缓存Domain)二级缓存:
  1. //Code Snippets Copyright http://lyj.cnblogs.com/
  2. <cache usage="read-only|read-write|nonstrict-read-write" region="ARegion"/>
  3. <class-cache class="NameSpace.Entity" usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>
  4. <collection-cache collection="NameSpace.Entity.CollectionProperty"
  5.           usage="read-only|read-write|nonstrict-read-write|transactional" region="ARegion"/>configure.EntityCache(ce => ce.Collection(e => e.Elements, cc =>        {            cc.RegionName = "MyCollectionRegion";            cc.Strategy = EntityCacheUsage.NonStrictReadWrite;        }));
复制代码
结语

在NHibernate3.0中,我们可以通过EntityCache扩展方法来实现对实体二级缓存的强类型配置了。有了这个扩展方法大家在一个配置类中配置所有Domain的二级缓存了,方便统一管理、随时修改和卸载。但是仔细想想,如果项目架构设计不好,这会导致配置类所在程序集会引用所有Domain项目,而有的Domain项目有时需要引用配置类所在程序集,很容易会造成双向引用。为了避免这个问题,现在该想想如何设计我们的项目架构咯,关于大型项目中使用NHibernate的完美方案有机会慢慢介绍。
参考资料

NHibernate Jira:Programmatic configuration of Cache
Fabio Maulo:NHibernate Configuration : Cache

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册