【问题标题】:NHibernate vs. EF 4.1+ [closed]NHibernate 与 EF 4.1+ [关闭]
【发布时间】:2012-06-12 19:01:30
【问题描述】:

我正在尝试主要在这方面决定 2 ORM 的优缺点。

  1. 与 Sql Server 2008 R2 和 2012 的兼容性。
    • 这非常重要,因为我们根本没有资源来调试对现有 MS 技术堆栈的不良支持。
    • 此外,自 2012 年以来的提前计划已经基本结束,并且已经制定了迁移到该计划的计划。
  2. 支持 .NET 4.0 和 4.5(即将推出)
    • 同样非常重要,原因与上述几乎相同。
  3. 事务处理和表提示,例如。 forcescan forceeek,读取未提交。
    • 很多时候查询优化器都能很好地完成工作,但有时我希望灵活地告诉它该做什么。
  4. 支持对话、自我跟踪附加和分离
    • 这有点基本。我讨厌长时间保持会话开放。尤其是在分布式计算/网络农场环境中。
  5. 能够在不破坏数据的情况下处理代码优先开发、创建和更新架构。
    • EF 4.1 似乎在这方面有所欠缺,尽管 4.3 的飞跃性更好。也比 NH 中的单独映射类更喜欢数据注释。原因是我希望能够在类中发送,并且能够在不扩大映射类方法的情况下创建持久性模型。
  6. 支持 IRepository 模式
  7. 支持 LINQ
    • 与上面的 (6) 有点关联,我希望对 linq 有很好的支持。我不希望开发人员在较低级别的实现中胡闹,并让自己陷入一种特定的 ORM
  8. 性能
  9. 支持批量 CRUD 操作,无需将数据加载到应用层。例如。我想将特定表的列中的所有行增加 1。我不想将其加载到内存中,并逐行递增。对于如此简单的操作,这将是疯狂的。 Linq2Sql 以前有 Magiq 来处理这种事情,NH 和 EF 有什么?
  10. 缓存、预加载、延迟加载、导航属性。
    • 坦率地说,我讨厌这些含蓄地做的事情。原因是很难区分缓存的内容、陈旧的内容和新的内容。在 EF 中,我通常会删除所有导航属性,因为我不希望这些属性与前 5 名一起加载,因为这是当前操作所需要的,但在流的更下游,另一个开发人员会尝试进行不准确的计数。
    • 所以我的个人政策 - 所有 SOA 都应该是无状态的,除非有充分的理由。如果您需要引用数据,请从持久性中获取。它会更慢,但代码会更具可读性和灵活性。
    • 同样用于缓存。它在分布式环境中足够复杂,我希望所有缓存都非常明确。如果开发人员想要针对缓存编写代码,则应该这样做,而不是针对 ORM 编写代码,并使其看起来好像是从持久性中提取新数据,而实际上他正在获取陈旧数据。
    • 现在的问题是,NHibernate 是否有任何概念/抽象可以使缓存、急切/延迟加载比 EF 中当前可用的更明确得多。在这种情况下,我不太关心开发的难易程度,我更关心的是清晰度和明确性。

另外,我不太关心 OSS 与专有论点。团队没有时间去窥探底层代码并开始弄乱其他人的代码。我更关心“它只是工作”的角度。

【问题讨论】:

  • 写得很好的问题,虽然我担心这对 SO 来说有点开放;这里的问题通常/经常有一些源代码,并且应该导致清晰,实用的答案。也许它更适合 Programmers.SE?

标签: .net entity-framework nhibernate orm fluent-nhibernate


【解决方案1】:

虽然我在another question 中写过其中一些问题,但我认为值得逐点回答。

  1. 两者都与所有 SQL Server 版本兼容
  2. 两者都与 .NET 4.x 兼容。 NH 的目标仍然是 3.5,这不是问题。
  3. 两者都有事务处理。两者都不支持原生查询语言中的查询提示,但都允许您使用 SQL。
  4. 两者都允许您重新连接断开的实体。我个人认为这不是一个好的做法(我更喜欢传递 DTO)
  5. 架构迁移在 EF 中更加成熟和灵活。映射在新罕布什尔州更好。它确实支持使用属性进行映射,这比 EF 的等效功能强大得多,您很快就会发现它甚至不支持基本的东西(例如指定小数字段的精度)
  6. 您可以在任何一个之上实施您的存储库。
  7. 两者都支持 LINQ。 EF 支持更广泛的查询,但有时会产生效率极低的查询。你不应该降低你的开发实践;每种查询方法都有其优点,优秀的开发人员应该知道这些选项。
  8. NH 的性能通常更好,因为它具有映射灵活性以及对批处理、缓存和 DML 语句的支持
  9. EF 不支持批量 (DML) 操作。 NH 确实如此,使用与 SQL 非常相似的 INSERT/UPDATE/DELETE 语句,但基于对象模型(例如,您可以使用点语法而不是显式连接来指定条件)
    • EF 不支持缓存,期间。有一些不受支持的样品尚未准备好投入生产。 NHibernate 中的所有缓存都是显式的(您指定要缓存的实体、集合和查询,多长时间等)。它支持像 memcached 这样的分布式缓存,因此它也可以处理过时的缓存数据。
    • 两者都允许您显式地预先加载引用和集合。在我看来,NH 有一个更好的代理设计,它不会用 FK 污染你的模型(这是一个很长的话题,如果你愿意,你可以发布一个后续问题)。和往常一样,在指定必须如何加载每个关系时,您确实有更大的灵活性。

简而言之:NH 更灵活,性能更好,毫无疑问。 EF 具有更好的迁移支持、更简单的学习曲线和更完整的 LINQ 提供程序。

【讨论】:

  • 很多很好的答案,但我发现这个答案是最客观和最相关的问题。谢谢。
【解决方案2】:

首先,我在各个方面都比较喜欢NHibernate。 Entity Framework 在 5.0 版中也遗漏了一些东西。

  1. 在 NHibernate 中添加新类型非常容易,因此如果 SQL Server 2012 有新类型,您可以实现相关方言/提供程序,但社区始终在工作
  2. 我知道 NH 团队正在努力支持 FW 4.5,EF supports 从 5.0 开始
  3. 使用 NH,您可以为所欲为
  4. NH 支持 Merge 方法重新附加实体,EF 也支持
  5. EF 不支持命名约定,NH 支持,我也在写一个基于 DataAnnotations 的自动映射器,here 旧版本的链接,等待 2 周的新版本
  6. 使用 NH 或 EF,您可以使用存储库和工作单元模式实现数据层,我还要在 NuGet 上发布这个包
  7. EF 完全支持 LINQ,NH 不支持,但您可以使用扩展 point 进行修补
  8. 我觉得性能差不多,NH更好地支持二级缓存,所以很容易防止对数据库的命中
  9. NH 有改进的批处理 support,我不知道 EF(特别是 5.0)
  10. NH 具有更好的扩展点实现,因此代理/缓存/日志记录比 EF 更强大,但在 EF 中您可以编写 wrapper 来获得所需的内容

最后,使用 NH 更容易实现 DDD 模式,因为映射更灵活。

【讨论】:

  • NH 映射如何更灵活?我发现 EF 4 fluent API 非常灵活,尤其是因为它的定义与实体类分开。
  • @MatteoMigliore 我喜欢你提出的包装器支持,这真是太好了!但是,是的,请说明 NH 比 EF 更灵活的原因是什么? EF 几乎允许您修改 edmx 并以您认为合适的方式进行映射,首先从代码开始。
  • NH 中的映射可以通过多种(多种)方式进行。 Read Fabio Maulo 关于映射的帖子。有兴趣可以等我的基于DataAnnotations的auto mapper包来快速切换NH和EF,反之亦然。
  • @MatteoMigliore - 我对您的自动映射器很感兴趣,它可以替代 Fluent NHibernate。你能指出我的文档,或者带有简单代码示例的博客文章吗?
  • @TomBushell 我在Nuget 上发布了一个旧版本。我将在两周内发布新版本,改进了自动映射所有内容并与 DDD 一起使用,等待它您也可以尝试 Fabio Maulo 的ConfOrm
【解决方案3】:

你可以使用 bltoolkit ;) -> http://www.bltoolkit.net/Doc.Linq.ashx

只需花 2 分钟时间阅读此内容 -> http://www.bltoolkit.net/Doc.LinqModel.ashx

但总之

  • 非常好的 Linq 支持
  • DML 操作 (nr 9)
  • 出色的性能/批量支持
  • 生成的 Sql 非常棒
  • 枚举支持 ;-)
  • 没有延迟加载/实体跟踪/特殊的魔法缓存,你现在这些东西通常会导致问题
  • 没有神奇的功能 -> 更少的抽象 -> 更少的泄漏 -> 更少的麻烦 -> 更小的学习曲线

顺便说一句,它确实是 nr 3,它具有属性 TableFunction 和 TableExpression 以支持表值 UDF、提示和其他围绕表装饰。 因此,您可以编写自己的扩展方法以在 Linq 语句中使用 例如

[TableExpression("{0} {1} WITH (TABLOCK)")]
public Table<T> WithTabLock<T>()
    where T : class 
{
    return _ctx.GetTable<T>(this, ((MethodInfo)(MethodBase.GetCurrentMethod())).MakeGenericMethod(typeof(T)));
}

然后

using (var db = new TestDbManager())
{
    var q =
        from p in new Model.Functions(db).WithTabLock<Parent>()
        select p;

    q.ToList();
}

DML 操作示例

  db.Employee
    .Where(e => e.Title == "Spectre")
    .Set(e => e.Title, "Commander")
    .Update();

【讨论】:

    【解决方案4】:

    你不想要它们中的任何一个。您将无法指定任意表格提示,并且它不会像您希望的那样灵活。

    如果所有这些都是要求,那么地球上没有 ORM 可以满足这些要求。

    编辑:

    根据您的评论。 nHibernate 将为您提供最强大的功能,但代价是设置模型的复杂性增加。有一些工具可能会有所帮助,但每种工具都有其优点和缺点。

    EF 更易于配置和使用,但功能较弱。 nHibernate 正好相反。您必须在功能和复杂性之间做出选择。

    顺便说一句,关于批量操作和其他操作,您可以直接从框架中为此类操作发出 SQL。或者调用存储过程。

    【讨论】:

    • 不,我将选择 2 个邪恶中最小的一个。这么说吧。
    • 谢谢,但我需要详细信息。我讨厌令人讨厌的复杂性,我需要证实为什么存在复杂性的论据。以上是我寻找的东西我想知道复杂性将如何帮助我实现这个目标。
    • @Alwyn - 我不太明白你的意思。您需要证实为什么存在复杂性的论据?它在那里,因为这就是他们建造它的方式。 nH 随着时间的推移而发展和演变,并且它的大部分早期实践都是向前发展的。他们本可以以类似于 EF 的方式构建 nHibernate,但他们没有,唯一的原因是因为他们总是按照他们的方式来做。已经有许多尝试将 nH 带入现代配置机制,其中一些甚至在核心 FW 中获得了一些控制。最后,虽然。可配置性 = 复杂性。
    • @Alwyn - 问为什么某事是这样是没有建设性的,它就是这样。问题是您是否愿意按原样使用它。 nH 为您提供了很大的灵活性,但是您将要编写大量的 XML,或者尝试使流利的 nH 工作。或任何数量的其他副项目。
    • 请不要对我的回复感到生气,感谢您的时间和回复,但我一直在寻找与上述 Matteo 的回答类似的更多逐点比较。我没有遗留系统,我只想知道哪些框架更能满足我的需求。上面详细说明了这些需求。 p.s.我不希望开发人员直接编写 sql,这违背了拥有 ORM 的意义。
    【解决方案5】:

    只是添加到其他答案...

    Ricardo Peres 前几天写了一篇非常不错的,不偏不倚的 NHibernate 和 Entity Framework 比较。它可能会对您的研究有所帮助。

    你可以在这里找到它:http://weblogs.asp.net/ricardoperes/archive/2012/06/07/differences-between-nhibernate-and-entity-framework.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-03-28
      • 1970-01-01
      • 1970-01-01
      • 2011-07-18
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 2011-07-30
      相关资源
      最近更新 更多