比较NHibernate和实体框架

openkk 7年前
   <div id="news_body">     <p> 葡萄牙的一位开发者 <a href="/misc/goto?guid=4958344597859485615">Ricardo Peres</a> 最近发布了一篇文章,以看起来无偏见的形式对领先的两种 .NET ORM:NHibernate 和实体框架进行了比较。 我们建议考虑使用这两种框架的人都应该读下他的文章,<a href="/misc/goto?guid=4958344598662017548">NHibernate 和实体框架之间的区别</a>,另外还将指出一些关键的区别。</p>     <p> 从架构上看,NHibernate 基于 Java 的 Hibernate ORM。 Ricardo 写道:</p>     <blockquote>      <p>在 NHibernate 中,工作单元和配置项以及模型实例都相互独立。 你首先会创建 Configuration 对象,在其中你会指定所有 NHibernate 设置,像要使用的数据库和语言、批处理的大小、映射关系等等,然后你会依此构建 ISessionFactory。 ISessionFactory 会持有与特定数据库绑定的模型和元数据,以及来自于 Configuration 对象的设定,并且,一般每个进程中只有一个实例。 最终,你会基于 ISessionFactory 创建 ISession 的示例,它是工作单元(Unit of Work)以及标识符地图(Identity Map)的 NHibernate 表现形式。 这是一种轻量级的对象,它本质上会根据需要打开和关闭数据库连接,并跟踪与之相关的实体。 ISession 对象很容易创建和销毁,因为所有的模型复杂性都存储在 ISessionFactory 和 Configuration 对象中。</p>     </blockquote>     <p> 评论者 Morten Mertner 说:“我永远都不会使用 NHibernate。 尽管它拥有很棒的特性列表,但它并非一种能够轻松使用的产品,而且 API 和设计中始终带有遗传自 Java 的味道(同样,很多 Java API 都太企业化,并且架构过于庞大;结果会与你想要的大相径庭)。”</p>     <p> 实体框架遵循的是更加传统的 .NET 设计,其中所有一切都封装在单独的 <a href="/misc/goto?guid=4958344599450335437">ObjectContext</a> 或者 <a href="/misc/goto?guid=4958324973688701717">DbContext</a> 中。 这让使用对象更加简单,但是缺点在于“类并没有因此是轻量级的,因为它有与 NHibernate 类似的内容,并且一般不会看到这样的例子:实例可以缓存在字段中。”</p>     <p> 对于映射,NHibernate 和实体框架之间的关键区别在于,前者支持基于 XML 的映射文件,该文件可以独立部署。 在理论上,这让你可以针对不同的数据库 schema 使用相同的对象模型,而不需要重新编译应用程序。 但在实践中很少这么使用。</p>     <p> 在很多方面古老一些的 NHibernate 要优于实体框架。 Ricardo 提供了更多细节,并简要地总结如下:</p>     <ul>      <li>关联: 都支持一对一、一对多、多对多,但是 NHibernate 还支持各种排序、未排序和索引的选项。 它甚至还有不变的(immutable)、索引的(indexed)列表。</li>      <li>缓存: NHibernate 提供了带有大量实现的二级缓存。 实体框架没有任何对此内建的支持,但是有些<a href="/misc/goto?guid=4958344600988099153">增加二级缓存的例子</a>。</li>      <li>ID 生成: NHibernate 提供了大概十二种策略,这取决于你如何计算。 实体框架只为 SQL Server 提供了主要的三种: 标识符列、GUID、和手动赋值。</li>      <li>事件: 实体框架只有两种基于事件的扩展点: <a href="/misc/goto?guid=4958344601783708270">ObjectMaterialized</a> 和 <a href="/misc/goto?guid=4958344602574757986">SavingChanges</a>。 “NHibernate 拥有非常丰富的事件模型,暴露了超过 20 种事件,有些针对同步前执行(synchronous pre-execution),有些针对异步后执行(asynchronous post-execution)”。</li>      <li>级联: “两种框架都支持集合和关联的级联: 当实体被删除的时候,相关的子实体也会被删除。 NHibernate 还提供了一种特性,可以把子实体上的外键设置为 NULL,而不删除它们。”</li>      <li>清理变更: NHibernate 提供了一种自动模式,其中在必要的时候会保存变更,像“如果有一种实体类型的脏实例,而查询是针对这种实体类型执行”。 <a href="/misc/goto?guid=4958344603372374015">FlushMode.Auto</a> 实际上是默认值,但偶尔会看到<a href="/misc/goto?guid=4958344604172503414">由于自动清除而导致性能问题</a>。</li>     </ul>     <p> 也有一些领域中,实体框架会比 NHibernate 好,比方说:</p>     <ul>      <li>跟踪变更: 尽管两种框架在工作单元级别默认都能够跟踪变化,而实体框架还提供了<a href="/misc/goto?guid=4958344604970669860">自我跟踪实体(self-tracking entities)</a>。</li>      <li>整合: 实体框架当然会与 Visual Studio 和各种 ASP.NET 以及 WCF 类库有很好的绑定。</li>      <li>文档: “这是另一种实体框架表现非常好的地方: NHibernate 缺少针对初学者的文档,并且也没有与其最新版本同步的最新 API 参考。”</li>      <li>查询: Craig 写到:“NHibernate 有更丰富的特性,但有一个领域除外,那就是对 Linq 的支持。 因为对于很多用户来说,Linq 或者其它查询语言都是 ORM 中最可见的部分,它会让人对功能产生错误印象。”</li>     </ul>     <p> 还有某些领域,两种框架都可以做出改进,像批处理功能。 当需要真正支持 SQL 的高级特性——像通用表表达式——的时候,两种 ORM 框架都无法支持 <a href="/misc/goto?guid=4958193864039269840">SQL Alchemy</a>。</p>     <p> 我们应该发现两个项目都很活跃,经常会有定期的改进。 所以,如果二者都能够满足你的最小需求,那么考虑就更多集中在程序库的设计模式和哲学上,而不是在特性列表上。</p>     <p> <strong>查看英文原文:</strong><a href="/misc/goto?guid=4958344606508104928">Comparing NHibernate and Entity Framework</a></p>     <div id="come_from">     来自:      <a id="link_source2" href="/misc/goto?guid=4958344607311609563" target="_blank">InfoQ</a>     </div>    </div>