代码之家  ›  专栏  ›  技术社区  ›  Asaf R

实体框架不信任投票-与.NET 4相关?

  •  60
  • Asaf R  · 技术社区  · 15 年前

    我决定为一个大项目设计一个orm,并决定使用ado.net实体框架,特别是它与.net 4一起发布的新版本。在我寻找英孚信息的过程中,我偶然发现了 ADO .NET Entity Framework Vote of No Confidence 我不知道该怎么拿。

    不信任投票是在2008年的某个时候写的,目的是说服微软听取对ef v1的具体批评。

    目前还不清楚在不信任投票中所做的声明是否仍然有效(在.net 4中),以及是否足够严肃到可以使用其他解决方案。NHibernate是一个成熟的替代品,但我不知道它会带来什么问题。我通常更倾向于使用ms解决方案,主要是因为我可以依赖于与vs的集成以及它们对开发人员的支持。

    我会很感激的 实例 不信任投票中提到的问题如何影响到现实世界的项目。 更重要的是,在ef中所做的声明是否仍然与.net 4相关?

    4 回复  |  直到 9 年前
        1
  •  64
  •   Community CDub    8 年前

    我一直认为,“不信任投票”的基本内容是试图使用EF,就好像它是NHibernate的克隆。事实并非如此,即使在ef 4中试图使用ef,就好像它是nhibernate的仿制品一样,也可能会以失败告终,尽管在失败之前你可能会走得更远一些。作为一个简单的例子,大多数人在nhibernate中使用linq的基础很小,如果有的话,但是我不认为你在ef中有效率。 完全 除非你大量使用linq。

    另一方面,我已经很成功地使用了ef 1本身的条款,并设法不允许人们在博客文章中的索赔得到的方式,使之为我工作。我期待着在ef 4中使用许多新特性,但我很乐意随时为一个结构良好的ef 1项目工作。(就这一点而言,我也很乐意与nhibernate合作,不会因为它没有英孚那样的表现而批评它。)

    因此,我试图以一种微妙的方式建议,在你决定“在不信任投票中提出的主张是否仍然有效(在.NET 4中)……”之前,你必须首先决定这些主张是否 对你和方式都有效 工作。 如果你对o/r的个人理解是与nhibernate紧密相连的,那么ef 4对你来说可能还是二流的。另一方面,如果你愿意学习ef的工作方式,那么甚至ef 1都可能比你听说的要好。

    为了直接解决“不信任”索赔,并检查其实质内容和EF4中的变化:

    过分关注实体的数据方面会导致实体架构降级:

    这是对实体框架的实体数据模型的误解。(或者,如果你愿意的话,可以有不同的意见)但是不管怎样,这都是一个特性,而不是一个bug。实体框架是围绕数据服务的更一般情况而设计的,而不仅仅是O/R建模。将行为放在从数据服务返回的实体上会导致corba风格的灾难。与orms不同的是,在某种程度上,您被困在orm黑盒子中的任何类型中,而实体框架模型则被期望投射到业务类型上。在这种情况下, 映射的实体类型甚至永远不会具体化。

    这是实体框架模型和许多其他orms之间的实质性区别。就我个人而言,我发现将业务行为与o/r映射分离要比将它们放在一起更干净一些。你不必同意这个想法,但这显然是一个设计决定,而不是一个疏忽。

    处理延迟加载不足所需的多余代码:

    无论好坏,ef 4都有延迟加载。

    我说“不管好坏”,因为延迟加载使生成多余的数据库查询变得非常容易。只要你密切关注引擎盖下的情况,它就可以正常工作,但大多数人不会这样做。我发现 projection 在大多数情况下,可以更好地替代延迟加载、紧急加载或显式加载。

    尽管如此,有时延迟加载还是很方便的。所以我很高兴看到EF4中加入了这个。

    共享的规范模型与软件最佳实践相矛盾:

    很难理解这是怎么回事,因为有些辅助文本甚至连英语都不连贯,例如:

    由于缺乏沿着实体框架的详细工具,易于失败的规范模型方法并不困难。

    本节 似乎 建议实体框架对复杂系统使用单一的规范化数据模型施加某种需求,或者至少是强烈的偏见。我不确定我是否同意,但鉴于本节没有任何具体的例子,很难说清楚。所以我会告诉你我在这个问题上的偏见,你可以同意或不同意我的观点:

    对一个大系统使用单一模型通常是错误的,这取决于系统实际有多大。然而,实体框架中的任何内容都不需要使用单个模型。另一方面,实体框架,特别是版本1中的实体框架,并没有特意使组合多个模型变得容易。

    现在,一个复杂系统的单个大型应用程序可能会像单个大型数据模型一样犯很大的错误。因此,实体框架不应该轻易地将许多小模型组合到一个过大的应用程序中;这只会将一个问题替换为另一个问题。

    另一方面,我认为用一种适合问题领域的方式分区的服务轻松构建一个大型系统是有意义的。我认为wcf数据服务(一种独立于实体框架的技术,但它非常支持实体框架)对此非常有用。

    我确实认为,实体框架在未来的某个版本中,可以在必要时更容易地将两个或三个模型组合到一个应用程序中。你现在可以这样做了,但需要一些手工工作。但正如我上面所说,我不想通过促进/鼓励创建一个过大的应用程序来“修复”一个过大数据模型的问题。

    缺乏持久性无知会导致业务逻辑更难读、写和修改,从而导致开发和维护成本以夸张的速度增加:

    本节提出了我认为错误的主张:

    实体框架通过阻止在实体类中包含业务逻辑来鼓励贫血的领域模型反模式。

    见上文。我认为实体类型的工作是在对象空间中的关系空间之间进行映射。根据单一责任原则,这些类型只需在其唯一工作发生变化时进行修改。如果业务流程发生变化,则这是与o/r映射无关的职责。其他orms的局限性可能会在分离这些职责时设置技术障碍。如果设计纯度的成本过高,在技术要求的情况下,可以改变规则。但我强烈支持使用行为较少的实体类型。

    在当前状态下,不能独立于数据库对ef实体类进行有效的单元测试。

    This is just wrong . 写这篇文章的人不明白他们在说什么。我们的单元测试都没有涉及到数据库,而且很多都涉及到ef。

    就本节标题的实质内容而言,EF4有所变化。如果这有助于您的设计,那么现在就有可能拥有完全不了解持久性的实体类型。然而,从words实体框架的最早版本开始,您就可以投射到pocos上。所以当需要的时候,坚持和无知总是存在的。对实体类型本身的持久性无知允许使用持久性无知对象进行更改跟踪。这在某些情况下可能有用。但是它是一个比关于单元测试的虚假声明小得多的案例子集,这大大减少了文档所表达观点的影响。

    团队环境中与源代码管理的过度合并冲突:

    合并XML真的那么困难吗?如果是这样的话,也许应该研究一个新的合并工具。我不觉得这有问题。

    然而,这里有一个真正的问题,尽管,再一次,它比文件声称的要窄得多。我不想重复我的话,我会把你指向 my post on that subject

    在ef 4中,可以使用代码优先模型,而不是xml模型,以便将模型拆分为许多不同的文件。

        2
  •  8
  •   Arve    15 年前

    实体框架自版本1以来得到了改进 blog post 从一个nhibernate贡献者比较nhibernate和实体框架4.0。

        3
  •  5
  •   Zackary Geers    9 年前

    编辑:这以前是真的,但现在不是了。

    作为一个同时使用实体框架和NHibernate的人…我强烈建议服用氨纤维酸酯。通常,如果有自由/开源软件和微软技术,我建议微软技术,但我强烈反对英孚。我在工作中每天都使用EF4,因为EF,我们必须创建很多解决方案。两年前,我用了英孚一年左右,后来换了公司,过去一年我一直在英孚工作。两年前,NHibernate领先EF4。

    这是他们提到的要点。

    团队环境中与源代码管理的过度合并冲突:

    据我所知,这是部分修复的。他们把设计师的位置数据移到了.edmx的底部,所以这不再是一个可怕的问题,但仍然很烦人。如果我和一个同事同时尝试修改.edmx,我们可能会遇到可怕的合并冲突,因为文件的整个底部用于在设计器中存储表的位置数据。我们解决这个问题的方法是使用svn文件锁定,这样我们就不会对它进行双重编辑。或者忽略锁定,如果遇到合并冲突,我只接受它们的更改并重做我的工作。我的大部分变化都不大,需要很长时间才能重新做。如果这是唯一的问题,我会接受的。

    如果你先使用代码(在ef 4.1中),这是没有问题的。

    处理延迟加载不足所需的多余代码:

    他们在4.0中添加了延迟加载。

    但它还是像垃圾一样装着预制件。紧急加载很慢,这是需要加快代码速度时的常见优化。我遇到了这样的情况:当我宁愿使用紧急加载时,我必须对数据库进行10K+的调用。我们已经对它进行了计时,在许多情况下,进行多个数据库调用(执行 myobject.TablenameReference.Load() 在循环中)到本地数据库,然后使用 .Include("Tablename") . 是的,我知道这是反直觉的,但数字不会说谎。此外,无法指定fetch策略,因此无法指定是否加入fetch。所以我想说它已经改进了,但还不如nhibernate好。

    过分关注实体的数据方面会导致实体架构降级:

    是的,这仍然是真的。同样一个很好的例子是order.status。我们非常希望它是一个枚举,但是由于ef的设计方式,除了使它成为字符串之外,我们没有其他选择。它们可能会在将来解决枚举问题,但表和对象之间的映射方式缺乏控制才是真正的问题。nhibernate允许您指定进行映射的方法,以处理这种情况。

    为了从craig stuntz的响应中扩展一个点,ef被设计为如果您想要获取数据模型,并直接从中选择。(即 myModel.Orders.Where(order => order.Status == "NEW").Select(order => order.Customer.FirstName, order=> order.Customer.LastName) )如果你不想影响数据库,ef的模型最终很难编写自动化测试。如果您想要一个存储库,在那里您需要一个满足某些条件的对象,并且它返回整个对象,这就是nhibernate更好的工作方式。(即 var order = myOrderRepository.GetByStatus(OrderStatus.New) )

    我对ef的另一个问题是它完全缺乏扩展性。我们遇到的一个问题是订单状态有枚举。但是如果我们这样做 myModel.Orders.Where(order => order.Status == OrderStatus.New.ToString()) ,EF将在该查询上崩溃,因为它不知道.toString()方法。它使我们的代码变得非常丑陋,因为我们不能添加对它的支持。还有很多内部的方法,所以我们需要引起一个奇怪的行为发生,我们不能这样做。

    如果您使用的是nhibernate,linq为nhibernate添加了许多特性,使其更好。使用基于约定的模型,大多数映射只需要很少的代码。如果您使用的是现有的数据库,nhibernate允许您指定要使用的非标准约定,然后让它们映射,一切都很容易管理。EF4.0(我不认为4.1)不支持这样的东西。

    我希望这能帮到你。

        4
  •  0
  •   robert_d    15 年前