实体框架4:为所有实体创建单个图表是否有意义?

时间:2010-10-05 20:32:54

标签: entity-framework-4 poco ado.net-entity-data-model

我写了一些关于实体框架的假设,然后是几个问题(所以请纠正我错在哪里)。我正在尝试使用EF 4的POCO。

我的假设:

  • EF图表只能存在一个数据上下文。
  • 数据上下文可以引用多个实体。
  • 如果您有两个数据源,比如MS SQL服务器和Oracle,EF需要两个不同的图来访问数据。
  • EF图表数据上下文是“工作单元”,对图上的任何内容都有一个Save()。 (当然你可以将它包装在UnitOfWork类中,但它基本上具有相同的职责)。

假设这是正确的,这是我的问题:

  • 如果您没有将所有实体保留在同一个EF图表上,那么如何维护数据完整性,如果没有“客户”,“订单”就不能存在?这仅仅是一个存储库的功能只是为了验证完整性而加载数据,还是我们“尝试/捕获”数据库参照完整性错误?

  • 您不会为每个实体创建EF图吗?例如,我不希望客户的更改和产品的更改一起写入,因为它们什么都没有彼此做(在同一图表上使用它们会导致它们被一起写入)。或者EF图的范围是否涵盖存储在同一存储介质中的所有类似实体?

将这样的实体分开,或只是拥有一个包含所有实体的图表是不是常态?我会想到后者,但我的想法越来越好。

2 个答案:

答案 0 :(得分:35)

拥有一个包含所有实体的大型EDM通常不是一个好习惯,不建议使用。
使用一个大型EDM将导致以下几个问题:

元数据加载时间中的性能问题:
随着模式文件的大小增加,解析和为此元数据创建内存模型所花费的时间也会增加。

视图生成中的效果问题:
视图生成是一个将用户提供的声明性映射编译到客户端实体Sql视图中的过程,该视图将用于查询实体并将其存储到数据库。该过程在第一次运行查询或SaveChanges时运行。视图生成步骤的性能不仅取决于模型的大小,还取决于模型的互连方式。如果两个实体通过继承链或关联连接,则称它们是连接的。类似地,如果通过外键连接两个表,则它们是连接的。随着模式中连接的实体和表的数量增加,视图生成成本也会增加。

凌乱的设计师表面
当您从大型数据库模式生成Edm模型时,设计器表面会混杂许多实体,并且很难理解您的实体模型总体如何。如果您对实体模型没有很好的概述,那么您将如何自定义它?

智能感知体验不是很好:
当您从具有1000个表的数据库生成Edm模型时,您将最终得到1000个不同的实体集。想象一下,当您在VS代码窗口中键入“context。”时,您的intellisense体验将如何。

混乱的CLR命名空间:
由于模型模式将具有单个EDM名称空间,因此生成的代码将将类放在单个名称空间中。

有关更详细的讨论,请查看 Working With Large Models In Entity Framework – Part 1

解决方案:
虽然没有开箱即用的解决方案,但它建议您应该 模型中自然断开连接的子集 ,这意味着根据您的域模型,您应该来使用不同的域模型集,每个域模型包含相关对象,而每个集都是不相关的并且与另一个集断开。中间没有外键可能是分离的好兆头。这是有道理的,因为在大型模型中,通常您的应用程序不需要将数据库中的所有表映射到一个实体模型才能工作。

即使这种分离不是100%可能 - 意味着有一些表的子集没有外键到数据库中的其他表 - 它仍然鼓励你将它们分开。执行此操作时,您必须负责适当地设置外键。没有导航属性允许您获取表示此外键的实体。当然,如果需要,您可以在另一个容器中手动查询此实体。

此外,有关如何在重用类型时将一个大型实体模型拆分为较小实体模型的一些提示和技巧,请查看: Working With Large Models In Entity Framework – Part 2

关于您的问题:订单客户属于同一个自然域,应保存在同一个EDM中。就像我说的那样,你可以将它们分散到2个不同的实体数据模型中,但是你必须负责设置适当的外键,或者你将获得运行时异常,同样的代码, Customer 产品应保存在单独的实体数据模型中。遵循这些规则,您可以在数据访问层中提出定义良好的域集设计。

答案 1 :(得分:11)

我意识到这个问题是关于 EF4 但我相信很多刚刚“开关”的人将会通过谷歌来到这里,并会阅读这个以及批准的答案并制作基于它的决定即使他们使用的是EF5(如果你坚持使用.Net 4.0,也可以使用EF4.4)

EF5 允许每个edmx 多个图。至少对我的团队来说,这是一个大问题,因为它允许我们在不需要单独的edmx文件的情况下直观地分离实体。除了(显然)“杂乱的设计师表面”,Zim博士的观点仍然有效。

有多个edmx文件的缺点,最大的一个是即使你为每个文件创建单独的命名空间,也不能复制实体名称。是的,如果你真的在设计系统“代码优先”,那么这应该不是问题。但是,我们中的许多人(大多数)都将EF添加到已经建立在已经规范化的关系数据库之上的现有系统上。

“但正常化是的事情,对吗?”好吧,如果你使用关系数据库是的。 “但是,如果我使用EF,为什么会这么重要?”一个常见的“规范化”表是Address。可能的情况:公司(业务/办公室的位置)和联系人(可能是“远程”工作人员,因此他们不在业务地点),他们都有一个指向地址的FK。使用一个edmx文件用于公司,一个用于联系人(即使使用不同的命名空间)都包含地址表,代码将编译,但在运行时你会得到这样的美:

Multiple types with the name 'Address' exist in the EdmItemCollection
in different namespaces. Convention based mapping requires unique names
without regard to namespace in the EdmItemCollection

您可以更改EF使用的映射,但在执行实施时您会遇到其他“问题”,并且大多数人都使用默认映射,因此这样的论坛不会有很多相关的问题和答案。

您还可以将地址表的模型名称分别重命名为“ContactAddress”和“CompanyAddress”,但这会让人觉得它们确实是不同的类型。好的,所以他们 不同类型的EF,但不是在数据库中,正如我所说,我们大多数人“生活”在将EF加入现有系统的世界中,现有数据存储是一个关系数据库。

这已经是一个冗长的“答案”所以我会在这里停下来。我只是想确保那些登陆这里的人因为他们搜索“多个edmx”而没有意识到EF4和EF5之间存在显着差异,他们意识到并意识到他们可能需要做更多的调查。