在 entity framework 中添加具有相同 table 的第二个一对一关系
Adding a second one-to-one relationship with the same table in entity framework
我正在进行代码优先 entity framework 设计。
我有一个 table,帐户,其中有一个 属性,主管:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
}
效果很好。
但是,我希望在 class 中添加一位候补主管:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
public Account AlternateSupervisor { get; set; }
}
当我 运行 添加迁移 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 为何生成这样的迁移的任何信息。
那么为什么 Entity Framework 试图将 Supervisor 重命名为 AlternateSupervisor 以及如何强制它生成两个链接?
编辑:这个问题已经按照最初的要求得到了回答。但是,我想补充一点,正如所问的那样,这个问题在领域内并没有多大意义。谁听说过一个账户只能监管另一个账户?该关系是一对多关系,通过使用 WithMany 而不是 WithOne 来解决。
EF Core 无法按照惯例将多个 one-to-one
映射到同一实体。您必须使用 Fluent API
执行以下操作:
你的 Account
class:
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; }
}
然后在DbContext
的OnModelCreating
如下:
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
模型 class 中。如果您不明确需要这些,那么 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);
}
我正在进行代码优先 entity framework 设计。
我有一个 table,帐户,其中有一个 属性,主管:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
}
效果很好。
但是,我希望在 class 中添加一位候补主管:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
public Account AlternateSupervisor { get; set; }
}
当我 运行 添加迁移 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 为何生成这样的迁移的任何信息。
那么为什么 Entity Framework 试图将 Supervisor 重命名为 AlternateSupervisor 以及如何强制它生成两个链接?
编辑:这个问题已经按照最初的要求得到了回答。但是,我想补充一点,正如所问的那样,这个问题在领域内并没有多大意义。谁听说过一个账户只能监管另一个账户?该关系是一对多关系,通过使用 WithMany 而不是 WithOne 来解决。
EF Core 无法按照惯例将多个 one-to-one
映射到同一实体。您必须使用 Fluent API
执行以下操作:
你的 Account
class:
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; }
}
然后在DbContext
的OnModelCreating
如下:
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
模型 class 中。如果您不明确需要这些,那么 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);
}