我正在做代码优先的实体框架设计。
我有一个表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来解决。
答案 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