Добавление второго отношения один-к-одному с той же таблицей в структуре сущностей - PullRequest
1 голос
/ 20 марта 2019

Я занимаюсь разработкой структуры кода для первого объекта.

У меня есть таблица, Учетная запись которой есть свойство, Супервизор:

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 генерирует миграцию следующим образом.

Так почему же Entity Framework пытается переименовать Supervisor в AlternateSupervisor и как я могу заставить его сгенерировать обе ссылки?

РЕДАКТИРОВАТЬ: На этот вопрос был дан ответ в том виде, в котором он был задан изначально. Тем не менее, я хотел бы добавить, что, как задано, вопрос не имеет особого смысла. Кто-нибудь слышал об аккаунте, который мог контролировать только один аккаунт? Это отношение один ко многим, которое разрешается с помощью WithMany вместо WithOne.

1 Ответ

1 голос
/ 20 марта 2019

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 из 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 должна быть следующей:

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);
 }
...