我遇到了一个奇怪的情况,想知道你是否可以帮助我。
我有包含一对多关系的实体。在父实体上,我不想添加作为子实体列表的导航属性。相反,我希望它包含子实体的单个实例。查询时,我将通过其中一列来约束子实体。
public class Parent
{
[Key]
public long ParentId { get; set;}
/// This is the normal behavior, when EFCore discovers this by convention it will
/// create a one-to-many relationship as expected
/// public List<Child> Children { get; set;}
/// This is my desired usage, but when the relationship is built it generates
/// a one to one and restricts creating multiple children with the same parent id.
public Child { get; set;}
}
public class Child
{
[Key]
public long ChildId { get; set;}
}
我尝试手动创建关系,但查询连接到了错误的列。
这要么成为一对一的关系,要么成为多对一的关系,其中一个孩子可以被许多父母参考。
假设一对一关系,EF 的默认行为和正常的标准化关系是通过 PK 连接两行。例如,采用与 CustomerDetails 表具有一对一关系的 Customer 表。这两个表都将使用 CustomerId 作为其 PK,并且客户配置为
HasOne(c => c.CustomerDetail)
与 .WithOne()
的关系,默认的 FK EF 选择的是 CustomerDetail 上的 PK。
如果您创建 CustomerDetail 以具有 CustomerDetailId 和 CustomerId,其中 CustomerDetailId 是 PK,EF 将使用它,除非您明确告诉它使用 CustomerId。这将使用
.HasForeignKey(cd => cd.CustomerId)
或 .HasForeignKey("CustomerId")
或者如果 CustomerDetail 不公开 CustomerId 属性。如果 FK 在 Customer (CustomerDetailId) 上,那么您需要 .HasForeignKey<Customer>("CustomerDetailId")
告诉 EF 在 Customer 端查找 FK。
在双向引用的情况下,另一侧有 CustomerDetail.Customer 并使用
.WithOne(cd => cd.Customer)
,那么 EF 应该 自动将相关 FK 结合起来。
使用这种形式的一对一关系时,请务必在 Parent.ChildId 或 Child.ParentId(无论您放置显式 FK 的哪一侧)上配置唯一索引。在代码优先中,这应该将实体关系配置为
IsUnique()
,或者向实体添加 [Index(nameof(ChildId), IsUnique=true)]
属性。如果没有唯一约束,它是一种多对一关系,其中多个父项可以通过具有相同子项 ID 的重复记录来引用同一个子项。 (或具有相同父 ID 的重复子项)