NHibernate是.NET平台上最著名的ORM框架,虽说出身于Java平台上的Hibernate,但是从外部看来这几乎就是一个.NET平台上的原生产品:有自己的社区,有自己的用户,有自己的商业支持,有利用C#特性的独立扩展。它不像Lucene.NET那样,一眼就能看出浓重的Java气息,Java的命名方式等等。我用NHibernate时间不长,而NHibernate的复杂程度也决定了我无法像了解LINQ to SQL那样容易。不过在使用了一段时间过后,还是对它有一定体会。有欣喜,有误解,也有抱怨。

这几篇文章里我不打算多谈NHiberante的优点,因为它的优势实在过于明显。如果不考虑Telerik ORM这样的商业框架(因为我没用过,完全不了解),.NET平台上开源和免费的ORM工具几乎没有NHibernate的对手:LINQ to SQL使用的确容易,上手非常快,某些功能也非常细致(稍后会谈到),但对于ORM工具的灵魂“Mapping能力”实在是不敢恭维。前一段时间我也简单了解了一下微软新出的Entity Framework,虽然也秉承了微软一贯的易用性(如强大的LINQ支持),在Mapping能力上也有切实的提高,但是在功能和一些细节控制上还远不如NHibernate。毕竟NHibernate是经历了多年发展,对于各种情况几乎都有应对措施。如延迟与否,是使用select还是join获取数据,是否在集合加载时附加条件。此外,NHibernate的Interceptor能力所带来的扩展性也是让我比较满意的,不过这点有机会再详细谈一下。

总之,目前NHibernate是我最满意的ORM框架。

那么现在进入正文内容。首先我想谈一下自己对NHibernate实现方式上的一个误解,这个误解让我对NHibernate一直有着错误的抱怨,我还在几篇文章里不断重复对NHibernate的错误指责,目前已经纠正,希望不会造成太大问题。

这个误解,是我一直认为NHibernate使用了一种简单的延迟加载方式。例如有这样一个对象:

public class Article
{
public virtual int ArticleID { get; set; }
public virtual string TagNames { get; set; }
}

在延迟加载的时候,我一直以为NHibernate只是通过Emit生成一个Article的子类,然后把属性覆盖成简单读写,例如:

public class Article$LazyProxy : Article
{
private string m_tagNames;
public override string TagNames
{
get
{
return this.m_tagNames;
}
set
{
this.m_tagNames = value;
}
}
}

这么做的问题自然是让TagNames属性原本的逻辑丢失了。如果对于失血的DTO模型,这自然没有关系,因为这些属性本身内部没有逻辑。但是,我习惯使用领域驱动设计(DDD)的方式来为产品建模,因此在这些属性中很可能拥有一些业务逻辑。例如改变对象的其他一些状态,同步至其他字段,或是触发事件等等。因此,丢失属性逻辑对我的影响是致命的,这意味着我必须“照顾”NHibernate的特性进行编程,而在进行建模时就开始考虑持久化逻辑是DDD实践中的一大问题——虽然软件开发不是理想化的,权衡是正常的,但如果NHiberante只能应付失血的DTO模型,那么它就对不起它的业界盛名了。

可惜的是,NHibernate没有在这里翻船——所以可能更应该说“值得庆幸”——它使用了一种维持原有业务逻辑的延迟代理写法:

public class ArticleLazyProxy : Article
{
public override string TagNames
{
get
{
var tagNames = ... // 加载数据
base.TagNames = tagNames;
return base.TagNames;
}
set
{
base.TagNames = value;
}
}
}

当然,这是我从“测试效果”中反推出来的情况,NHiberante的实际做法应该不会那么简单。如果您关注我的文章,会发现这就是我之前提出的最为理想的延迟代理实现方式,也是我在Eazy类库中使用的做法。我在实现了Eazy的基本功能之后,还因为它满足了我的要求而微微沾沾自喜了一把,谁知这一切早已被NHibernate拿下。我昨天晚上试验出这个结果之后也震惊了一把,不是因为NHibernate的强大(因为它本不该犯此低级错误),而是因为我不理解自己之前为什么会轻易地臆断NHibernate的做法?想象我还在多篇文章中抱怨过这点,昨天试验过后,我立即把自己能想到的无稽之谈都修改了。惭愧啊。

转自:http://blog.zhaojie.me/2009/09/my-view-of-nhibernate-2-virtually-everything.html

我对NHibernate的感受(1):对延迟加载方式的误解的更多相关文章

  1. NHibernate 有好几种数据库查询方式

    NHibernate 有好几种数据库查询方式 1.原生SQL var employeeQuery = Database.Session .CreateSQLQuery("select * f ...

  2. 我对NHibernate的感受(2):何必到处都virtual

    上一篇主要是在夸NHibernate实现的好,而这篇就完全是来抱怨的了.NHiberante有个毛病,就是如果是和数据库产生映射的类,就要求所有的public成员和protected成员必须是virt ...

  3. 我对NHibernate的感受(4):令人欣喜的Interceptor机制

    之前谈了NHibernate的几个方面,似乎抱怨的居多,不过这次我想谈一下我对Interceptor的感受,则基本上都是好话了.这并不一定是说Interceptor设计的又多么好(事实上它使用起来还是 ...

  4. 我对NHibernate的感受(3):有些尴尬的集合支持

    既然是一个ORM框架,那么自然是将O这一端映射R上.至于集合,是O这方面最常见,也是R这一边非常容易表示的关系.例如,一个问题(Question)可以包含多个回答(Answer),于是我的代码里就有这 ...

  5. [NHibernate]延迟加载

    目录 写在前面 文档与系列文章 延迟加载 一个例子 总结 写在前面 上篇文章介绍了多对多关系的关联查询的sql,HQL,Criteria查询的三种方式.本篇文章将介绍nhibernate中的延迟加载方 ...

  6. NHibernate教程(12)--延迟加载

    本节内容 引入 延迟加载 实例分析 1.一对多关系实例 2.多对多关系实例 结语 引入 通过前面文章的分析,我们知道了如何使用NHibernate,比如CRUD操作.事务.一对多.多对多映射等问题,这 ...

  7. 在 NHibernate 中一切必须是 Virtual 的吗?

    原文地址:Must Everything Be Virtual With NHibernate? 老赵在博文中 我对NHibernate的感受(2):何必到处都virtual 提到这篇文章,顺便翻译一 ...

  8. [NHibernate]立即加载

    目录 写在前面 文档与系列文章 立即加载 一个例子 总结 写在前面 上篇文章介绍了nhibernate延迟加载的相关内容,简单回顾一下延迟加载,就是需要的时候再去加载,需要的时候再向数据库发出sql指 ...

  9. [NHibernate]N+1 Select查询问题分析

    目录 写在前面 文档与系列文章 N+1 Select查询问题分析 总结 写在前面 在前面的文章(延迟加载,立即加载)中都提到了N+1 Select的问题,总觉得理解的很不到位,也请大家原谅,这也是为什 ...

随机推荐

  1. 20165203《Java程序设计》第三周学习总结

    教材学习内容总结 1.类: (1)类的声明:class+类名 (2)类体:成员变量的声明+方法(局部变量+语句) 注意: 方法体内声明的局部变量只在方法内有效和书写位置有关. 局部变量和成员变量同名: ...

  2. JS学习笔记(二)变量、作用域及内存问题

    一.基本类型和引用类型的值 变量可能包含两种不同数据类型的值:基本类型值和引用类型值. 基本类型值:简单的数据段. 引用类型值:可能由多个值构成的对象. 当将一个值赋给变量时,解析器必须确定这个值是基 ...

  3. 005 爬虫(requests与beautifulSoup库的使用)

    一:知识点 1.安装requests库 2.Brautiful soup 可以提供一些简单的,python式的函数来处理导航,搜索,修改分析树等功能. 她是一个工具箱,通过解析文档为用户提供需要抓去的 ...

  4. 【转】让你10分钟搞定Mac--最简单快速的虚拟安装

    文章出处:让你10分钟搞定Mac--最简单快速的虚拟安装http://bbs.itheima.com/thread-106643-1-1.html (出处: 黑马程序员训练营论坛) 首先说明一下. 第 ...

  5. 一台电脑如何安装多个版本的JDK

    1 . 准备两个版本的jdk我的两个jdk路径为:  C:\Program Files\Java\jdk1.6.0_43  C:\Program Files\Java\jdk1.8.0_25 2 . ...

  6. iOS Sprite Kit教程之场景的设置

    iOS Sprite Kit教程之场景的设置 Sprite Kit中设置场景 在图2.8所示的效果中,可以看到新增的场景是没有任何内容的,本节将讲解对场景的三个设置,即颜色的设置.显示模式的设置以及测 ...

  7. SKLearn数据集API(一)

    注:本文是人工智能研究网的学习笔记 数据集一览 类型 获取方式 自带的小数据集 sklearn.datasets.load_ 在线下载的数据集 sklearn.datasets.fetch_ 计算机生 ...

  8. ST-PUZZLE-2.0(一个益智游戏)

    注:未经博主允许不得转载. 原文链接:http://www.cnblogs.com/Blog-of-Eden/p/9060300.html 和 https://i-m-eden.github.io/2 ...

  9. 【洛谷】2474:[SCOI2008]天平【差分约束系统】

    P2474 [SCOI2008]天平 题目背景 2008四川NOI省选 题目描述 你有n个砝码,均为1克,2克或者3克.你并不清楚每个砝码的重量,但你知道其中一些砝码重量的大小关系.你把其中两个砝码A ...

  10. [OpenGL]纹理贴图实现 总结

    实现步骤 第一步:设置所需要的OpenGL环境 设置上下文环境 删除已经存在的渲染的缓存 设置颜色缓存 设置帧缓存 清除缓存 设置窗口大小 开启功能 编译shander 使用program 获取sha ...