问题
I am doing code-first entity framework design.
I have a table, Account, which has a property, Supervisor:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
}
This works beautifully.
However, I wish to add an alternate supervisor to the class:
public class Account
{
public int Id { get; set; }
public Account Supervisor { get; set; }
public Account AlternateSupervisor { get; set; }
}
When I run Add-Migration AddAlternateSupervisor, the generated code gives me the following:
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
}
As you can see, EF is trying to rename my reference from Supervisor to AlternateSupervisor. I don't want that, I want both Supervisor and AlternateSupervisor to reference other accounts.
I know that EF can't handle multiple many-to-many relationships, but these are one to one relationships. I can't seem to find any information on why EF is generating the migration like this.
So why is Entity Framework trying to rename Supervisor to AlternateSupervisor and how can I force it to generate both links?
EDIT: This question was answered as initially asked. However, I would like to add that as asked the question doesn't really make much domain sense. Who ever heard of an account that could only ever supervise exactly one other account? The relationship is a one to many relationship, which is resolved by the use of WithMany instead of WithOne.
回答1:
EF Core cannot map multiple one-to-one
with the same entity by convention. You have to do it with Fluent API
as follows:
Your 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; }
}
Then in the OnModelCreating
of the DbContext
as follows:
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);
}
Now everything will generate as expected!
Note: I have added SupervisorId
and AlternateSupervisorId
foreign key explicitly to the Account
model class for readability. If you don't want these explicitly then Fluent API
configuration should be as follows:
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);
}
来源:https://stackoverflow.com/questions/55252077/adding-a-second-one-to-one-relationship-with-the-same-table-in-entity-framework