Fluent API 和建立 1:* 关系
Posted
技术标签:
【中文标题】Fluent API 和建立 1:* 关系【英文标题】:Fluent API and building a 1:* relationship 【发布时间】:2017-07-22 12:40:21 【问题描述】:我有两个具有 1 对 1..* 关系的表(这意味着“状态”表中总会有特定 ID 的记录。
|Area| | Status |
------ -------------------
|[Key] ID | ----> |[Key] ID |
| Name| |[Key] Start Date |
| End Date |
我的数据层中建立了如下关系。
面积
HasMany(s => s.Statuses)
.WithRequired()
.HasForeignKey(s => s.Id);
状态
HasRequired(a => a.Area)
.WithMany(s => s.Statuses)
.HasForeignKey(s => s.Id);
我有一个通用的“AllIncluding”方法,用于收集相关数据。在调试器中,我可以查看查询并将其复制/粘贴到我的 Oracle 数据库并执行。它按我的预期工作并返回适当数量的行。 问题是在调试器中执行后,我浏览记录集并找到完全不同的数据集(缩减集)。
我的想法是,这是因为我按照图中的描述定义了键。我可以创建有关... the upper bound of the multiplicity of the Dependent Role must be '1'
的错误,还可以通过简单地修改状态表上的键来修改调试器中返回的记录集。
这似乎表明记录关系正在尝试删除状态表中的重复项以创建联接?我试图通过执行 group by trunc(start_date)
或其他类似查询在 Oracle 中重新创建它,但无法找到返回结果的确切行。
它只是证实了我的怀疑,Fluent API 中定义的映射和关系一定是错误的,但我不确定如何正确表示。
最终我只想在 Fluent API 中创建一个 1 -> 1..* 关系。
谢谢!
【问题讨论】:
查看类定义会有所帮助。似乎Status
实际上是Area
和一些存储“真实”状态的状态表之间的连接类,否则多对多关系似乎更合适。但是从你的描述中很难拼凑出发生了什么。
【参考方案1】:
这只是证实了我的怀疑,Fluent API中定义的映射和关系一定是错误的
使用 Fluent API 映射关系时要非常小心。具体来说,使用的With
方法重载必须与导航属性的存在/不存在完全匹配。 WithRequired()
和 .WithRequired(a => a.Statuses)
完全不同。当您没有导航属性时使用前者,否则使用后者。在您的情况下,您错误地使用了无参数重载。
始终在一处配置关系。这种关系是涉及两个实体的一件事——不需要在两个地方复制它,更重要的是,它容易出错。目前您有两种定义,一种是正确的(用于Status
),一种是不正确的(用于Area
)。最终结果是 EF 将它们视为两种不同的关系,进而导致错误的结果。
所以,要么从Area
中删除代码,然后将Status
中的代码原样保留:
HasRequired(s => s.Area)
.WithMany(a => a.Statuses)
.HasForeignKey(s => s.Id);
或从Status
中删除代码并在Area
中使用以下代码:
HasMany(a => a.Statuses)
.WithRequired(s => s.Area)
.HasForeignKey(s => s.Id);
【讨论】:
我试图从 Area 表中删除关系,但我开始收到一个错误,即找不到 Area_Id 值。我知道这是由于没有定义关系,所以添加了 .HasForeignKey() 子句。 我认为您可能正在做某事,因为我更改了状态表中的键以包含其他人并且看到了新结果 根据您显示的内容,表中必须没有Area_Id
列,因为根据您的设置,Status.ID
应该是 Area
的 FK。希望您在Status
配置中也使用了HaskKey(s => new s.Id. s.StartDate
之类的东西。无论如何,没有看到确切的实体类和完整的配置,我无话可说。以上是关于Fluent API 和建立 1:* 关系的主要内容,如果未能解决你的问题,请参考以下文章