关于 EF Core 中的“拥有”类型

Posted

技术标签:

【中文标题】关于 EF Core 中的“拥有”类型【英文标题】:On the "owned" types in EF Core 【发布时间】:2021-04-28 17:18:09 【问题描述】:

在我的项目中,我使用 EF Core fluent 配置,代码优先。我阅读了一些关于owned types 的信息,但下面的情况对我来说并不是很清楚:

假设我有一个Project 实体和一个ProjectType。 我应该将该属性映射为:

Entity<Project>.HasOne<ProjectType>(); 或者更确切地说是Entity<Project>.OwnsOne<ProjectType>();

ProjectType 实体应映射到表 ProjectType(ProjectTypeId, Name, Description)

据我所知,拥有的是

" 只能出现在其他导航属性中的类型 实体类型。这些被称为拥有的实体类型。实体 包含拥有的实体类型是它的所有者。拥有的实体是 本质上是所有者的一部分,没有它就无法存在”

就我而言

ProjectType 只能出现在Project 实体类型的导航属性上。ProjectType 本质上是Project 的一部分,没有它就无法存在”... 然而,为了创建一个单独的表,据我了解,我需要使用HasOne,而不是OwnsOne...如果有人更好地解释这个想法,那就太好了。非常感谢。

【问题讨论】:

我相信前者会创建一个单独的表,而后者不会。 @bolkay 查看我的 OP 更新;看来,我的 ProjectType 是 MS 定义所拥有的类型,但它似乎不应该在代码中使用它...... 查看生成的数据库结构。然后想想如果您想更改项目类型的名称并让所有所属项目立即反映此更改会发生什么。 @GertArnold 我没有发现问题。所有项目都使用项目类型的Id,而不是名称,作为参考。 当项目类型为自有类型时,其名称在项目表中。 【参考方案1】:

ProjectTypes 听起来像一个参考表,在应用程序的生命周期内可能会被修改,例如通过系统管理角色。使用新的“Owns”是一种约定,有助于强制实施特定类型的组合和关系数据模型中的表链接等概念。

一个更好的组合示例:假设您有一个项目,并且作为项目的一部分,有一些相当大且不经常使用的细节。诸如图像或其他二进制数据之类的东西,或者可能是一些大文本。当您获取一个或多个项目时,将这些 BLOB/CLOB 详细信息包含在 Project 表中可能会导致灾难,因此您将它们规范化为一个名为 ProjectDetails 的单独相关表,或者可能是几个相关表。这样,在大多数情况下,当您使用 Project 并加载这些实体时,您不必一直担心拉回这些大字段,您可以引用 ProjectDetails 以仅在实际需要时包含它.由于 ProjectDetails 本身并没有真正的用途,它不需要 DbSet 或类似的东西,因此我们可以设置从 Project 到 OwnsOne ProjectDetails 的关系。

另一方面,ProjectType 可能有一个 DbSet 来在配置应用程序的过程中建立新的项目类型。您可能还想根据项目类型关联其他与项目相关的详细信息。在这种情况下,将 Project 设置为 HasOne ProjectType 会更有意义。我们可以有一个项目类型的 DbSet 来管理,其他实体也可以按项目类型、项目阶段/阶段等进行过滤。

OwnsHas 之间的数据库架构而言,没有区别。这只是关于 EF DbContext 将如何与实体一起工作。

使用Owns 的其他常见示例是链接表。例如,您有一个在订单、客户等之间共享的地址表。两者都不是“拥有”地址,但他们确实拥有自己的链接表:订单拥有 OrderAddress,客户拥有 CustomerAddress。这些实体“有”一个地址。我们可能仍希望查看地址,因为它们代表物理位置,将订单等关联到不同位置与“调整”为物理位置记录的详细信息之间存在差异。 (即更正街道名称或市镇)无需分别处理超出订单或客户范围的 OrderAddresses 或 CustomerAddresses。

【讨论】:

感谢您为主题带来一些清晰。遗憾的是,文档(OP 中的链接)中缺少如此重要的细节。因为我的 ProjectType 正式符合拥有的类型文档定义。 “就数据库架构而言,Owns 和 Has 之间没有区别。这只是关于 EF DbContext 期望如何与实体一起工作”是真的吗?我认为Owns 会将孩子嵌入到父级中,而Has 会创建一个新表。 通过一对一的关系,它可以嵌入到主表(似乎是默认行为)或单独的表中。对于一对多,它使用单独的表。我想不出一个用例,我想在同一个表中嵌入一个拥有的实体,而不是可能的 JSON 列,如果它甚至受支持的话。我遇到的一个更常见的场景是使用 Has/Owns 来启用表拆分。 :) 但绝对值得考虑。

以上是关于关于 EF Core 中的“拥有”类型的主要内容,如果未能解决你的问题,请参考以下文章

EF CORE中复杂类型的映射

EF CORE中复杂类型的映射

Entity Framework Core - EF Core 2.2 - 'Point.Boundary' 属于接口类型('IGeometry')

EF Core 使用许多用户定义的表类型执行过程

如何让 EF Core 6 支持 DateOnly 类型

EF Core:实体类型“用户”需要定义主键