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

Posted

技术标签:

【中文标题】实体框架 4:为所有实体创建单个图表是不是有意义?【英文标题】:Entity Framework 4: Does it make sense to create a single diagram for all entities?实体框架 4:为所有实体创建单个图表是否有意义? 【发布时间】:2011-04-21 12:22:31 【问题描述】:

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

我的假设:

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

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

如果您不将所有实体都保留在同一个 EF 图上,您如何保持数据完整性,例如“订单”没有“客户”就无法存在?这仅仅是一个存储库加载数据只是为了验证完整性的功能,还是我们“尝试/捕获”数据库引用完整性错误?

您不会为每个实体创建一个 EF 图吗?例如,我不希望对客户的更改和对产品的更改一起编写,因为它们什么都没有相互关联(将它们放在同一个图表上会导致它们被写在一起)。或者 EF 图的范围是否包含存储在同一存储介质中的所有相似实体?

这样划分实体是常态,还是只用一个图表来保存所有实体?我会认为是后者,但我的想法越来越好。

【问题讨论】:

吹毛求疵:实际上,在 Entity Framework 中,有 Object Contexts - 而不是 DataContext(它们是 Linq-to-SQL 的等价物) 我的坏习惯。实际上,我们只是将它们称为 POCO 代码的“上下文”。我们关闭了代码生成,所以没有看到 EF 实际使用了什么。 【参考方案1】:

我知道这个问题是关于 EF4,但我相信很多刚刚“进行转换”的人最终会通过 Google 来到这里,并会阅读这个和批准的答案并做出即使他们使用的是 EF5(如果您使用 .Net 4.0,也可以使用 EF4.4)做出基于它的决定

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

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

“但是标准化是一件的事情,对吧?”好吧,如果您使用的是关系数据库,是的。 “但是,如果我使用的是 EF,这有什么关系呢?”一个常见的“标准化”表是地址。可能的情况:公司(业务/办公室的位置)和联系人(可能是“远程”工作人员,因此他们不在业务位置)并且他们都有一个指向地址的 FK。使用包含 Address 表的 Company 和 Contact 的一个 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 使用的映射,但是在执行实施时您会遇到其他“问题”,并且大多数人使用默认映射,因此像这样的论坛不会有很多相关的问题和答案。

您还可以将 Address 表的模型名称分别重命名为“ContactAddress”和“CompanyAddress”,但这会让人产生一种错觉,即它们实际上不是不同的类型。好的,所以它们在 EF 中不同类型,但在数据库中没有,正如我所说,我们大多数人“生活”在将 EF 附加到具有现有数据存储的现有系统的世界中是一个关系型数据库。

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

【讨论】:

【参考方案2】:

拥有一个包含所有实体的大型 EDM 通常不是一种好的做法,也不建议这样做。 使用一台大型 EDM 会导致几个问题,例如: 元数据加载时间的性能问题: 随着模式文件大小的增加,解析和为此元数据创建内存模型所需的时间也会增加。 视图生成中的性能问题: 视图生成是将用户提供的声明性映射编译为客户端实体 Sql 视图的过程,该视图将用于查询实体并将其存储到数据库中。该过程在第一次发生查询或 SaveChanges 时运行。视图生成步骤的性能不仅取决于模型的大小,还取决于模型的互连程度。如果两个实体通过继承链或关联连接,则称它们是连接的。同样,如果两个表通过外键连接,则它们是连接的。随着模式中连接的实体和表的数量增加,视图生成成本也会增加。 杂乱的设计师表面: 当您从大型数据库模式生成 Edm 模型时,设计器表面会出现大量实体,并且很难理解您的实体模型的整体外观。如果您对实体模型没有很好的了解,您将如何自定义它? Intellisense 体验不是很好: 当您从具有 1000 个表的数据库生成 Edm 模型时,您最终将得到 1000 个不同的实体集。想象一下,当您输入“上下文”时,您的智能感知体验会如何。在 VS 代码窗口中。 凌乱的 CLR 命名空间: 由于模型模式将具有单个 EDM 命名空间,因此生成的代码会将类放置在单个命名空间中。 如需更详细的讨论,请查看 Working With Large Models In Entity Framework – Part 1 解决方案: 虽然对此没有开箱即用的解决方案,但它建议您应该模型中的自然断开子集意味着根据您的域模型,您应该来使用不同的域模型集,每个域模型都包含相关的对象,而每个集合都是不相关的,并且与另一个不相关。中间没有外键可能是分离的好兆头。这很有意义,因为在大型模型中,通常您的应用程序不需要将数据库中的所有表都映射到一个实体模型才能工作。 即使这种分离不是 100% 可能的——这意味着有一些表的子集具有指向数据库中其他表的外键——它仍然鼓励您将它们分开。当你这样做时,你必须负责适当地设置外键。没有导航属性允许您获取表示此外键的实体。当然,如果需要,您可以在另一个容器中手动查询此实体。 此外,有关如何在重用类型的同时将大型实体模型拆分为较小实体模型的一些提示和技巧,请查看:Working With Large Models In Entity Framework – Part 2 关于您的问题:OrderCustomer 属于同一个自然域,应该保存在同一个 EDM 中。就像我说的那样,您可以将它们分散在 2 个不同的实体数据模型上,但是您必须负责设置适当的外键,否则您将获得运行时异常,出于同样的原因,Customer产品 应保存在单独的实体数据模型中。按照这些规则,您可以在数据访问层中提出定义明确的域集设计。

【讨论】:

如果您创建一个大图表,为每个表创建一个存储库,并使用 UnitOfWork() 使用相同的数据上下文将公共存储库组合在一起会怎样?这样您就可以拥有所需的任意数量的数据上下文,并且只使用其中必要的表。 你当然可以这样做,但它绝对不会让你摆脱上述 5 个问题中的任何一个 :) 在上一个示例中,您将 Order 和 Customer 放在同一个 EDM 中,但将 Order 和 Product 分开?我不明白...

以上是关于实体框架 4:为所有实体创建单个图表是不是有意义?的主要内容,如果未能解决你的问题,请参考以下文章

我应该共享实体框架上下文还是为每个操作创建一个新上下文?

通过实体框架中的多个表获取值?

使用 XSLT 创建网站是不是有意义 [关闭]

实体框架 4 Single() vs First() vs FirstOrDefault()

使用实体框架 4.1 代码优先方法将一对一的表关系映射到单个实体

存储库模式和聚合根模式和实体框架