关于.net:实体框架4与NHibernate

Entity Framework 4 vs NHibernate

关于Web上的实体框架第一版(也在StackOverflow上)已经讨论了很多,很明显,当我们已经有了更好的选择(如NHibernate)时,这不是一个好的选择。但是我找不到实体框架4和NHibernate的良好比较。我们可以说,今天nhibernate是所有.NET表单中的领先者,但是我们可以期望Entity Framework 4取代nhibernate离开这个位置吗?我认为,如果微软真的在EF4中注入了非常好的功能,它可以给NHibernate带来很好的竞争,因为它集成了Visual Studio,更容易使用,而且在大多数商店里,微软的产品总是被优先考虑。


在"自我跟踪实体"中,EF4对n层开发有一个开箱即用的答案。没有人发布过类似的NHIB代码。

NHIB有许多功能,但还没有作为EF4的一部分被提及。其中包括二级缓存集成。它还具有更大的继承映射灵活性,更好地与存储过程/数据库函数/自定义SQL/触发器集成,支持公式属性等。在我看来,它基本上是一个更成熟的ORM。


更新:我从4.0版开始就没有使用过实体框架,所以我的答案可能会过时。我的项目中仍然使用NH或纯ADO.NET。我甚至不想看4.0以后英孚的新功能,因为NH工作得很好。

实际上,当您同时使用这两种方法时,比较它们非常容易。EF4有一些严重的限制,我可以列举一些我自己遇到的限制:

EF4问题:

  • 预加载和调整结果:EF4预加载系统(include("path")使用循环联接生成不正确的SQL,对于多对多关系,执行数千(不是字面上的)时间会变慢,然后手动编写SQL(实际上不可用)。
  • Materializer无法实现关联实体:如果您认为可以通过提供自己的SQL查询来克服前面的问题,那么您就错了。EF4无法从join sql查询中具体化(map)关联实体,它只能从一个表中加载数据(因此,如果您有order.product,select*from order left join product将只初始化order对象,product将保持为空,认为所有必需的数据都已在query中获取以初始化它)。这可以通过使用EFextensions社区附加组件来克服,但是您为此而必须编写的代码确实很难看(我尝试过)。
  • 自我跟踪实体:许多人说自我跟踪实体对于N层开发很酷,包括这个线程中的首要答案。我想我还没有给他们一个尝试,我可以说他们不是。每一个输入都可以伪造,你不能简单地接受用户发送给你的更改并将它们应用到数据库,为什么不给用户直接的数据库访问呢?无论您以何种方式加载用户将要从数据库更改的数据,检查数据是否存在,执行权限检查等。您不能信任用户对其发送到服务器的实体的状态,您无论如何都必须从数据库加载此实体并确定其状态和其他内容,因此此信息是无用的,自我跟踪和除非您为内部使用做了一个私有的受信任的N层系统,在这种情况下,您可能只提供纯数据库访问。(这就是我对ST实体和N-Tire的看法,我对N-Tier的经验不是很丰富,所以如果我误解了这里的一些内容,它可能会改变,请评论它)

  • 日志记录、事件、集成业务逻辑:EF4就像黑匣子,它做一些事情,而您不知道它做什么。只有一个保存更改的事件,在该事件中,您可以在DB发生某些事情之前将需要运行的一些业务逻辑放入其中,并且如果您需要在发生某些事情之前对业务对象应用某些更改,则必须在ObjectStateManager中进行挖掘,这非常难看,代码可能会变得巨大。例如,如果您使用存储库模式,以及以干净的对象方式对数据库进行更改时要通知的内容,那么使用EF就很难做到这一点。

  • 可扩展性:所有的ef代码都是私有的和内部的,如果你不喜欢某些东西(如果你认真使用ef的话,你不会喜欢很多),你不会轻易地改变这一点,事实上,我确信从头开始编写自己的orm会更容易(我做了),然后让ef按你的需要工作。举个例子,看看ef extensions源代码,它是基于扩展方法和不同的"黑客"使ef变得更有用,代码非常难看(这不是作者的错,当ef中的所有内容都是私有的时,这是扩展它的唯一方法)。

我可以继续写关于英孚的不好的东西,写20页对我来说是多么痛苦,也许我会写。

那NHibernate呢?这是完全不同的水平,就像把php和c比较,ef4就像石器时代,ef比nhibernate落后10年,实际上,hibernate是从2001年开始的。如果你有空闲时间学习和打开NHibernate,就去做。


事情是这样的。在我看来,NHibernate和实体框架实际上是为两个不同的受众设计的。在构建具有复杂映射、公式和约束(基本上是任何企业)的系统时,nhibernate都是我的选择。如果我想用简单的数据访问实现实际运行,我将使用实体框架或LinqtoSQL。NHibernate不像EF那样有清晰的"拖放"体验。两者都有各自的优点和缺点。坦率地说,把它们比作苹果毫无用处。


如果你认为你可能想要在mono上运行你的代码,那么nhibernate可能是一个更好的选择,不管功能清单上说什么…

编辑,2012年8月13日:

实体框架是开放源码的,目前已包含在Mono中,截至2.11.3。这个答案现在已经过时了,不应该依赖它。

http://weblogs.asp.net/scottgu/archive/2012/07/19/entity-framework-and-open-source.aspx


我的看法是,EF4.0从1.0开始已经走了很长一段路,并且在功能上已经赶上了NHibernate,但还没有全部实现。

然而,它是微软,开箱即用,做95%的应用程序需要它做的事情。然而,NHibernate已经做了很多年了。5.0版或6.0版可能会赶上,甚至超过NHibernate。

这是我的建议——如果你有时间学习两者,那么就去做吧。选择其中一个的原因有很多。如果你正在为一家公司编写代码,那么期望成为熟悉英孚的有能力的员工是很现实的,因为英孚在所有书籍中都有,孩子们在大学里学到了什么。如果英孚能满足你的要求(在说"是"之前,先仔细考虑一下这个问题),那么现在这是一个非常好的解决方案,几年后它可能(好的,很可能会)超过NHibernate。

NHibernate是一种非常成熟的产品,在EF上使用几年,很可能会做任何你想做的事情,然后做一些。它已经是一段时间以来最好的ORM了,很多人使用它。


我认为事实上,英孚4将有能力使用POCO和延迟懒惰加载将非常大。我可以肯定地看到它在新版本中获得了吸引力。


有一个明显的趋势,越来越多的英孚普及比NHiberiate,见图片。

NHibernate vs Entity Framework


我的2分:我们在桌面客户机上使用ef进行一些绑定等-没有高负载。服务器端的nhib—利用无状态会话、hilo id生成和批处理。是相当快的插入3K+消息,以分贝每秒。而且它非常灵活,支持许多DBS,Wich对我们的产品至关重要。


对于逻辑层,使用LINQ组合直接映射到存储过程似乎是最简单的方法。没有XML。仅为使用频率较低或不适合存储过程的有趣查询生成SQL。

对象通过标准SP加载和存储。这种方法允许使用两个SQL登录。一个用于通过SP进行类访问(仅执行权限),另一个用于允许直接表访问的逻辑LINQ模块。


根据人气在ORM中选择并不是最好的选择。在过去的2年里,我试着搬到英孚,我能说的就是,为什么我还要尝试?

atm我对ef的看法是:"它适用于非常小的非常小的系统,不超过3个表,关系小于1(0更好)"。

我为什么这么想?1。尝试更新一个断开连接的图形并看到您的模型划痕;

  • 试着用深继承的树来构建TPH,你会发现你被孤立到一个层次,否则系统就会崩溃。

  • 试着做一些更麻烦的查询,并看着整个系统耗尽堆栈:d…溢出经常发生。

  • 映射XML数据类型基于扩展或最"讨厌"的NotMapped属性…更糟的是。

  • 尝试将SQL查询混合到LINQ中以获得更多的Finner查询,这样您就可以打破墙LOL。

  • 最后也是最重要的一点,ef不支持属性公式("NH为遗留数据库提供的一个很棒的资源"),也不支持同一个表和相关表的复杂类型映射。

  • 那是我的10CC。