Spiga

NHibernate 3版本新特性

2010-12-15 09:26 by 李永京, 8334 visits, 收藏, 编辑

2010年12月4号Fabio Maulo发布了NHibernate 3.0.0.GA正式版本,基于.Net3.5和.NET 3.5 Client Profile平台,主要改变是增加Loquacious配置和基于Lambda表达式查询和Linq查询。你可以到这里下载NHibernate 3.0.0.GA。接着Fabio Maulo陆续发布了NHibernate.Caches.3.0.0.GANHibernate.Validator.1.3.0.Alpha1ConfORM 1.0.1.2

下面是NHibernate 3版本新特性:

Configuration部分

在Configuration部分新增两种Loquacious-Configuration方式:流配置(fluent-configuration)和lambda表达式配置(lambda-configuration)

fluent-configuration顾名思义,使用Fluent API配置SessionFactory属性,提供强类型支持、编译期错误检查等。你可以通过SessionFactory fluent配置了解详细信息。例如使用流配置方式最小配置NHibernate:

var configure = new Configuration();
configure.SessionFactory()
    .Named("Demo")
    .Proxy.Through<ProxyFactoryFactory>()
    .Integrate
        .Using<MsSql2008Dialect>()
        .Connected
           .Using("ConnectionString");

lambda-configuration是利用C#3.0扩展方法(Extension Methods)配置SessionFactory属性。你可以通过Configuration篇之SessionFactory lambda配置Cache lambda-configuration配置了解详情。例如使用lambda表达式方式最小配置NHibernate:

var configure = new Configuration();
configure.SessionFactoryName("Demo");
configure.Proxy(p => p.ProxyFactoryFactory<ProxyFactoryFactory>());
configure.DataBaseIntegration(db =>
{
    db.Dialect<MsSql2008Dialect>();
    db.Driver<SqlClientDriver>();
    db.ConnectionString = ConnectionString;
});

新增WcfOperationSessionContext类提供对WCF环境的支持,我们直接配置"current_session_context_class"为"wcf_operation"在WCF环境中应用NHibernate。

Mapping部分

对于Mapping部分,Fabio Maulo完全重构了NHibernate.Cfg.MappingSchema代码部分,提高了性能。同时为NHibernate专门设计了一个配置ORM工具——ConfORM:解析Domain结构,按照模式适配器和自定义配置生成HbmMapping类,避免NHibernate通过读取XML映射文件反序列化等方式生成HbmMapping类的过程。不过ConfORM不是NHibernate的一部分,需要另外单独下载。李永京在自己的博客中介绍了这个工具,可以参考ConfORM概览原理OneToOne语义ManyToMany语义Component语义。我们可以这样使用:

var orm = new ObjectRelationalMapper();
orm.TablePerClass<Domain>();
var mapper = new Mapper(orm);
var hbmMapping= mapper.CompileMappingFor(new[] { typeof(Domain) });

在Configuration类中新增了AddDeserializedMapping(HbmMapping mappingDocument, string documentFileName)方法,可以直接解析HbmMapping,这样选择不使用xml文件而是ConfORM。例如上面使用ConfORM生成的hbmMapping我们加到Configuration中:

var conf=new Configuration();
//...
conf.AddDeserializedMapping(hbmMapping, "Domain");

Query部分

在NHibernate 3.0.0版本中,Query方式新增了Linq支持和强类型查询API(QueryOver)两种查询方式。

QueryOver是Lambda表达式方式的条件(Criteria)查询,可读性强且支持property-renaming特性。可以参考QueryOver in NH 3.0。例如下面查询Name为李永京、按照Age降序的Person集合:

var query = s.QueryOver<Person>()
    .Where(p => p.Name == "李永京")
    .OrderBy(p => p.Age).Asc
    .List();

Linq基于HQL AST分析器的Linq Provider实现,由Steve Strong贡献者开发的,底层使用第三方Re-Linq开源框架。不过NHibernate3.0.0版本提供的Linq查询还处于Bate阶段,Fabio Maulo准备发布3.1版本修复Linq查询BUG。可以参考:NHibernate.Linq标准查询增强查询自定义扩展。我们使用ISession接口的Query<T>()扩展方法创建一个NHibernate.Linq查询。

var query = session.Query<Person>().Where(o => o.Name == "李永京").ToList();

其他

还有其他一些新特性:

重构Logging Abstraction日志系统模块:移除对log4net.dll程序集依赖,现在可以用CommonLogging或者NLog日志系统。可以参考Using NLog via Common.Logging with NHibernate

属性延迟加载和No Proxy关联特性:具体使用方法可以参考Ayende的NHibernate new feature: Lazy PropertiesNHibernate new feature: No proxy associations两篇博文。它仅支持Castle的bytecode-providers,不支持Spring.Net和LinFu代理。

映射支持XDocument、System.Uri、XmlDoc、Local & Utc DateTime类型。

bytecode-providers程序集更新:Castle使用2010年11月15号发布的2.5.2正式版本,即Castle.Core.dll程序集。LiuFu使用2010年4月5号发布的1.04版本,即LinFu.DynamicProxy.dll程序集。

改变

如果从NHibernate2.1.2版本升级到NHibernate3.0.0版本,需要注意下面改变:

  1. NHibernate3.0.0版本不支持.Net3.5以下版本,即.Net2.0版本不可以升级到NHibernate3.0.0版本。
  2. [NH-2392]ICompositeUserType.NullSafeSet方法签名改变。
  3. [NH-2199]maps/dictionaries中null值不再不加提示地忽略/删除。
  4. [NH-1894]SybaseAnywhereDialect删除,代之以SybaseASA9Dialect。删除了Sybase Adaptive Server Enterprise (ASE)方言。
  5. [NH-2251]Dialect中的GetLimitString签名变化。
  6. [NH-2284]删除了过时的成员。
  7. [NH-2358]DateTimeOffset类型现在不再是DateTime的替代。

实用工具

最近一年,网络上出现了一些优秀的NHibernate工具:

  1. HQL Language Service for Visual Studio:为我们编写HQL查询提供了智能提示和语法验证检查功能。
  2. NHibernate Profile:可视化NHibernate性能检测优化工具。
  3. Visual NHibernate:可视化设计和映射工具。
  4. Mindscape NHibernate Designer:VS设计工具,类似于EF设计器。

其中HQL Language Service for Visual Studio是一款开源工具,其他都是商业版本。

未来发展

据我了解的情况来看,将来的版本发布预计一两个月后会发布3.1版本,然后就升级至.Net4平台开发NHibernate 4版本,主要就是逐步改写内部代码去掉Iesi.Collections.dll,使用.Net4提供的ISet集合和添加一些新功能,比如Duck Typing(鸭子类型)等。另外NHibernate源码将迁移到CodePlex网站,使用Hg版本控制。

第一次在InfoQ网站上发表,链接地址:NHibernate 3版本新特性。感谢Allen Lee对本文的审校。

希望本文对你有所帮助。

Add your comment

29 条回复

  1. #1楼 Allen Lee      2010-12-15 09:31
    看完你的新闻之后突然有点想试试NH,将来还要找你讨教一下哦~

    P.S.百会写写做得不是一般的差,排版乱了还不止,生成的HTML包含了一大堆垃圾...
     回复 引用 查看   
  2. #2楼 初中程序员      2010-12-15 09:36
    一直有个疑问 如今有了linq,ADO.NET Entity Framework 还用NHibernate吗?
     回复 引用 查看   
  3. #3楼[楼主] 李永京      2010-12-15 09:38
    @Allen Lee
    恩,还是使用Web编辑器比较简单,另外NH可以试用下,现在已经和微软的ef没啥区别了,也有linq查询,相比而言更易使用。主要麻烦的地方多了配置和映射环节,不过几行代码就可以搞定了。
     回复 引用 查看   
  4. #4楼 liulun      2010-12-15 09:42
    wcf是要序列化的
    不知道NH的延迟加载功能是不是在序列化之后就无效了
    EF有POCO能解决这个问题,还没研究过;
     回复 引用 查看   
  5. #5楼[楼主] 李永京      2010-12-15 09:42
    @初中程序员
    各有各的好处和特性。比如微软的不支持别的数据库方言。NH有很多新的特性,比如延迟加载、Filter、二级缓存、托管对象状态和很多扩展。
     回复 引用 查看   
  6. #6楼 liulun      2010-12-15 09:44
    @李永京
    EF4也有延迟加载了
     回复 引用 查看   
  7. #7楼[楼主] 李永京      2010-12-15 09:47
    @liulun
    恩,延迟加载的实际意义是按需要加载,比如你先获取一个对象、在之后按需加载其集合,NH重要的一个功能就是Session托管,你wcf每次请求开启个session,这时造成Session关闭的错误。如果你想WCF支持延迟加载是有办法的,就是利用一个字典去保存那些开启的Session,当需要延迟加载的时候,去找其在特定的Session中去获取对象就可以了,这些我已经做出来了...
     回复 引用 查看   
  8. #8楼[楼主] 李永京      2010-12-15 09:48
    @liulun
    特性我说的是属性和一对一的延迟加载
     回复 引用 查看   
  9. #9楼 菌哥      2010-12-15 09:48
    那Fluent NHibernate还有存在的意义吗?
     回复 引用 查看   
  10. #10楼[楼主] 李永京      2010-12-15 09:51
    @菌哥
    这个真的没有了,因为FNH的本质还是生成xml,通过反序列化的途径去生成HbmMapping。
     回复 引用 查看   
  11. #11楼 liulun      2010-12-15 09:53
    @李永京
    WCF是以数据契约交互的数据的
    假设一个对象包含一个子对象list
    服务端通过NH得到这个对象之后
    要序列化之后再给客户端
    我认为
    序列化的过程就访问到了这个子对象list
    就已经把子对象全部取出来了
    所以对于客户端来说,这个延迟加载已经失效了
    不知道是不是这样
    请赐教~~~
     回复 引用 查看   
  12. #12楼 Weck      2010-12-15 09:54
    哇,太好了,就在等楼主发3.0的资料,多发点啊
     回复 引用 查看   
  13. #13楼 liulun      2010-12-15 09:56
    @李永京
    另,
    我是在腾讯微博上关注你的allen;
    http://t.qq.com/liulun
     回复 引用 查看   
  14. #14楼[楼主] 李永京      2010-12-15 09:57
    @liulun
    恩,就是这样,实际没有延迟加载的功能了,是全部读取,但是可以写个框架做到先只获取这个对象不加载其集合,需要的时候在读取...这才是WCF支持的延迟加载。
     回复 引用 查看   
  15. #15楼 liulun      2010-12-15 10:03
    @李永京
    如果做框架的话就要破坏WCF固有的序列化的机制
    我现在考虑用EF4了
     回复 引用 查看   
  16. #16楼 paul_wbc      2010-12-15 10:12
    引用初中程序员:一直有个疑问 如今有了linq,ADO.NET Entity Framework 还用NHibernate吗?

    同疑惑
     回复 引用 查看   
  17. #17楼 LeoXing      2010-12-15 10:42
    引用paul_wbc:
    引用初中程序员:一直有个疑问 如今有了linq,ADO.NET Entity Framework 还用NHibernate吗?

    同疑惑

    有了C#还需要Java么?
     回复 引用 查看   
  18. #18楼 鹤冲天      2010-12-15 12:37
    好文,支持!
     回复 引用 查看   
  19. #19楼 mrxliu      2010-12-15 15:38
    你这篇文章都上了INFOQ了
     回复 引用 查看   
  20. #20楼 king2003      2010-12-17 16:17
    不知楼主,有没这样的查询:
    序号 版块 管理员
    1. 产品管理 张三,王平
    2. 新闻管理 李六,林小华

    这里面很像上面的三张表,也是多对多关系
    不知楼主对这样的查询,用NHibernate是怎么实现的?
     回复 引用 查看   
  21. #21楼 App00001[未注册用户]2010-12-17 17:01
    Linq的问题,还是NHibernate的问题

    1.Contains的错误

    IList<string> userIds=new List<string>();

    var users = from u in session.Query<User>()
    where (userIds.Contains(u.UserId)==false)
    select u;

    当userIds.count=0时,应该全选出来,结果一个也没选择出来。


    2.!=的错误

    var nCount = (from r in ActiveRecord.Query<Reasons>()
    where (r.Reason == reason)
    && (r.ReasonsId != reasonsId)
    select r).Count<Reasons>();

    当reasonId=string.empty, 答案是0,实际可能是1,当 reasonId=' '时,多了个空格,就正确了。

     回复 引用   
  22. #22楼 完美猪猪      2010-12-23 14:05
    永哥,
    新增WcfOperationSessionContext类提供对WCF环境的支持,我们直接配置"current_session_context_class"为"wcf_operation"在WCF环境中应用NHibernate。

    这句话能给出简单的代码例子吗?很期待!!

     回复 引用 查看   
  23. #23楼 Henley Gao      2010-12-27 10:09
    NorthwindDbCreator.cs我下载的 Nhibernate里的源码编译不过
     回复 引用 查看   
  24. #24楼 Henley Gao      2010-12-27 10:10
    NorthwindDbCreator.cs我下载的 Nhibernate里的源码编译不过,我用的VS2008
     回复 引用 查看   
  25. #25楼[楼主] 李永京      2010-12-27 10:18
    @Henley Gao
    删掉这个类,并注释相关代码,没有影响。
     回复 引用 查看   
  26. #26楼 会长      2011-02-12 13:54
    博主,你既研究NHibernate,又研究Linq。可否赐教一下您觉得在选择ORM技术时,是使用诸如第三方的Nhibernate呢,还是微软自己的Linq to sql呢,他们各有什么优劣,谢谢。
     回复 引用 查看   
  27. #27楼 初蕊[未注册用户]2011-03-03 16:06
    但是可以写个框架做到先只获取这个对象不加载其集合,需要的时候在读取...这才是WCF支持的延迟加载。
     回复 引用   
  28. #28楼 红旗飘飘      2011-05-17 10:11
    我也想知道怎么解决WCF中使用Nhibernate的问题。遇到表关联,客户端查询就出错。
     回复 引用 查看   
  29. #29楼 6572789      2011-11-24 13:13
    收藏,以后多多关注
     回复 引用 查看   
发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1906298 p1SjbsWJHfM=