EF 代码优先 - 配置一对零或一关系,无需共享 PK/FK

Posted

技术标签:

【中文标题】EF 代码优先 - 配置一对零或一关系,无需共享 PK/FK【英文标题】:EF code first - configure One-to-Zero-or-One relationship without shared PK/FK 【发布时间】:2017-05-24 16:45:33 【问题描述】:

我正在尝试在两个实体之间建立一对零或一的关系,并且我希望依赖实体仍包含其自己的 Indentity 列,而不是共享键。

我想尽可能地遵循约定,并且不明确声明任何不需要明确声明的内容(因此,没有不必要的数据注释或流畅的 api 子句)

实体:

public class File

    public int FileId get;set;
    //some omitted file properties
    public virtual Task Task get;set;


public class Task

    public int TaskId get;set;
    //some omitted task properties
    public int FileId get;set;
    public virtual File File  get;set;


 protected override void OnModelCreating(DbModelBuilder modelBuilder)
        
            modelBuilder.Entity<File>().HasOptional(f => f.Task).WithRequired(t => t.File);
            base.OnModelCreating(modelBuilder);
        

这会创建一个奇怪的关系,其中 TaskId 是 Tasks 表的 PK 和 FK 列。我认为这意味着它应该与文件 ID 具有相同的值? (这是一个问题:))

那么,如何让 TaskId 拥有自己的顺序值,并使 FileId 成为 Files 表的外键?

或者也许在 1-0..1 的情况下,我宁愿摆脱 TaskId 属性并让 FileId 成为 PK/FK 属性?

干杯!

【问题讨论】:

【参考方案1】:

不支持具有显式 FK 属性的双向 one-to-one 关系。

所以要么继续使用你现在拥有的 - Shared Primary Key association。只需从Task 中删除TaskIdFileId 属性之一,并将剩余的属性设为PK(EF 将自动将其用作FK,因为这是默认的EF one-to-one 关系模型)。

或者去掉Task中的FieldId属性,使用如下流畅的配置(都是必须的):

modelBuilder.Entity<File>()
    .HasOptional(f => f.Task)
    .WithRequired(t => t.File)
    .Map(m => m.MapKey("FileId"))
    .WillCascadeOnDelete();

但我建议使用第一种方法(如果没有特殊原因不这样做,就像现有数据库等一样),因为它得到更好的支持 - 第二种方法在 SQL 查询中包含一些 LEFT OUTER JOINs,正如你可以看到的那样发布EF - WithOptional - Left Outer Join?。

【讨论】:

非常感谢,很好的回答:)

以上是关于EF 代码优先 - 配置一对零或一关系,无需共享 PK/FK的主要内容,如果未能解决你的问题,请参考以下文章

一对零或一关系实体框架

在 SQL Server 中实现一对零或一关系

使用 CodeFirst 的 C# 一对零或一关系

实体代码第一个零或一到零或一关系

正确配置多对一关系 ef core

缺少列:具有共享 PK 的一对一映射上的 id