在实体框架中添加与同一张表的第二个一对一关系

Ste*_*hen 4 entity-framework ef-code-first entity-framework-core .net-core

我正在做代码优先实体框架设计。

我有一个表 Account,它有一个属性 Supervisor:

public class Account
{
  public int Id { get; set; }
  public Account Supervisor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

这很好用。

但是,我希望在班级中添加一名替代主管:

public class Account
{
  public int Id { get; set; }
  public Account Supervisor { get; set; }
  public Account AlternateSupervisor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我运行 Add-Migration AddAlternateSupervisor 时,生成的代码给了我以下内容:

public partial class AddAlternateSupervisor : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropForeignKey(
            name: "FK_Accounts_Accounts_SupervisorId",
            table: "Accounts");

        migrationBuilder.DropIndex(
            name: "IX_Accounts_SupervisorId",
            table: "Accounts");

        migrationBuilder.AddColumn<int>(
            name: "AlternateSupervisorId",
            table: "Accounts",
            nullable: true);

        migrationBuilder.CreateIndex(
            name: "IX_Accounts_AlternateSupervisorId",
            table: "Accounts",
            column: "AlternateSupervisorId",
            unique: true,
            filter: "[AlternateSupervisorId] IS NOT NULL");

        migrationBuilder.AddForeignKey(
            name: "FK_Accounts_Accounts_AlternateSupervisorId",
            table: "Accounts",
            column: "AlternateSupervisorId",
            principalTable: "Accounts",
            principalColumn: "Id",
            onDelete: ReferentialAction.Restrict);
    }
    // snip
}
Run Code Online (Sandbox Code Playgroud)

如您所见,EF 正在尝试将我的引用从 Supervisor 重命名为 AlternateSupervisor。我不希望那样,我希望 Supervisor 和 AlternateSupervisor 都引用其他帐户。

我知道 EF 不能处理多个多对多关系,但这些是一对一关系。我似乎找不到任何关于为什么 EF 生成这样的迁移的信息。

那么为什么 Entity Framework 试图将 Supervisor 重命名为 AlternateSupervisor,我该如何强制它生成两个链接?

编辑:此问题已按照最初的要求回答。但是,我想补充一点,正如所问的那样,这个问题实际上并没有多大意义。谁听说过一个账户只能监管另一个账户?该关系是一对多关系,通过使用 WithMany 而不是 WithOne 来解决。

Tan*_*jel 5

one-to-one按照惯例,EF Core 不能将多个映射到同一实体。你必须这样做Fluent API

你的Account班级:

public class Account
{
    public int Id { get; set; }

    public int SupervisorId { get; set; }
    public Account Supervisor { get; set; }

    public int AlternateSupervisorId { get; set; }
    public Account AlternateSupervisor { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后在OnModelCreatingDbContext,如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Entity<Account>().HasOne(a => a.Supervisor).WithOne()
            .HasForeignKey<Account>(a => a.SupervisorId).OnDelete(DeleteBehavior.Restrict);

      modelBuilder.Entity<Account>().HasOne(a => a.AlternateSupervisor).WithOne()
            .HasForeignKey<Account>(a => a.AlternateSupervisorId).OnDelete(DeleteBehavior.Restrict);
 }
Run Code Online (Sandbox Code Playgroud)

现在一切都会按预期生成!

注:我已经加入SupervisorIdAlternateSupervisorId外键可以明确地Account为可读性模型类。如果您不明确需要这些,则Fluent API配置应如下所示:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.Entity<Account>().HasOne(a => a.Supervisor)
                  .WithOne().OnDelete(DeleteBehavior.Restrict);

      modelBuilder.Entity<Account>().HasOne(a => a.AlternateSupervisor)
                  .WithOne().OnDelete(DeleteBehavior.Restrict);
 }
Run Code Online (Sandbox Code Playgroud)