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

时间:2019-03-20 00:55:46

标签: entity-framework .net-core ef-code-first entity-framework-core

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

我有一个表Account,其中有一个属性Supervisor:

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

这很漂亮。

但是,我希望为班级增加一名候补主管:

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

当我运行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
}

如您所见,EF试图将我的引用从Supervisor重命名为AlternateSupervisor。我不需要,我希望Supervisor和AlternateSupervisor都引用其他帐户。

我知道EF无法处理多个多对多关系,但是这些是一对一关系。我似乎找不到有关为何EF生成此类迁移的任何信息。

那么,为什么实体框架试图将Supervisor重命名为AlternateSupervisor,又如何强制它生成两个链接?

编辑:最初回答该问题。但是,我想补充一点,问到这个问题实际上并没有多大意义。谁曾听说过只能监督另一个帐户的帐户?这种关系是一对多的关系,可以通过使用WithMany代替WithOne来解决。

1 个答案:

答案 0 :(得分:1)

根据约定,EF Core无法将多个one-to-one映射到同一实体。您必须使用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; }
}

然后在OnModelCreating的{​​{1}}中进行如下操作:

DbContext

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

注意:我已将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); } SupervisorId外键显式添加到AlternateSupervisorId模型类中以提高可读性。如果您不想明确地指定这些,则Account的配置应如下所示:

Fluent API