EntityFramework Core 3.0 Fluent API Построитель отношений "многие ко многим", создающий дополнительные столбцы внешнего ключа - PullRequest
0 голосов
/ 04 августа 2020

Проблема в том, что ядро ​​EF создает дополнительные столбцы внешнего ключа для отношения «многие ко многим», хотя я указал, что такое внешние ключи.

У меня есть следующие модели сущностей, которые должны быть в отношении «многие ко многим»

ParticipantModel.cs

public class ParticipantModel
{
    public int Id { get; set; }

    public HashSet<ThreadsParticipants> ThreadsParticipants { get; set; } = new HashSet<ThreadsParticipants>();
}

ThreadModel.cs

public class ThreadModel
{
    public int Id { get; private set; }

    public HashSet<ThreadsParticipants> ThreadsParticipants { get; set; } = new HashSet<ThreadsParticipants>();
}

ThreadsParticipants.cs (объединение таблицы)

public class ThreadsParticipants
{
    public int ThreadModelId { get; private set; }

    public ThreadModel ThreadModel { get; private set; } = default!;

    public int ParticipantModelId { get; private set; }

    public ParticipantModel ParticipantModel { get; private set; } = default!;
}

И следующие конфигурации EntityTypeConfiguration s:

    public void Configure(EntityTypeBuilder<ParticipantModel> builder)
    {
        builder.HasKey(p => p.Id);
    }

    public void Configure(EntityTypeBuilder<ThreadModel> builder)
    {
        builder.HasKey(t => t.Id);
    }

    public void Configure(EntityTypeBuilder<ThreadsParticipants> builder)
    {
        builder
            .HasKey(tp => new { tp.ThreadModelId, tp.ParticipantModelId });

        builder
            .HasOne(tp => tp.ThreadModel)
            .WithMany()
            .HasForeignKey(tp => tp.ThreadModelId)
            .IsRequired();

        builder
            .HasOne(tp => tp.ParticipantModel)
            .WithMany()
            .HasForeignKey(tp => tp.ParticipantModelId)
            .IsRequired();
    }

При запуске add-migration блок, который создает таблицу ThreadsParticipants, генерируется как таковой:

            migrationBuilder.CreateTable(
            name: "MessageThreadsParticipants",
            columns: table => new
            {
                ThreadModelId = table.Column<int>(nullable: false),
                ParticipantModelId = table.Column<int>(nullable: false),
                ParticipantModelId1 = table.Column<int>(nullable: true),
                ThreadModelId1 = table.Column<int>(nullable: true)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_MessageThreadsParticipants", x => new { x.ThreadModelId, x.ParticipantModelId });
                table.ForeignKey(
                    name: "FK_MessageThreadsParticipants_MessageParticipants_ParticipantModelId",
                    column: x => x.ParticipantModelId,
                    principalTable: "MessageParticipants",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_MessageThreadsParticipants_MessageParticipants_ParticipantModelId1",
                    column: x => x.ParticipantModelId1,
                    principalTable: "MessageParticipants",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
                table.ForeignKey(
                    name: "FK_MessageThreadsParticipants_MessageThreads_ThreadModelId",
                    column: x => x.ThreadModelId,
                    principalTable: "MessageThreads",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Cascade);
                table.ForeignKey(
                    name: "FK_MessageThreadsParticipants_MessageThreads_ThreadModelId1",
                    column: x => x.ThreadModelId1,
                    principalTable: "MessageThreads",
                    principalColumn: "Id",
                    onDelete: ReferentialAction.Restrict);
            });

Почему эти дополнительные свойства внешнего ключа генерируются, когда я явно указал, какие у меня внешние ключи?

Ответы [ 2 ]

1 голос
/ 04 августа 2020

РЕДАКТИРОВАТЬ

Согласно комментарию @ Flater, причина в том, что конфигурация была указана дважды, поэтому был создан дополнительный набор столбцов.

Фактически удаление дуплексной конфигурации Fluent API «один ко многим» из конфигурации типа объекта ThreadsParticipants решает эту проблему, и дополнительные свойства больше не создаются. Когда эта часть конфигурации удаляется, EF использует соглашения об именах для выяснения взаимосвязи, поэтому нет необходимости явно указывать детали взаимосвязи.

    builder
        .HasOne(tp => tp.ThreadModel)
        .WithMany()
        .HasForeignKey(tp => tp.ThreadModelId)
        .IsRequired();

    builder
        .HasOne(tp => tp.ParticipantModel)
        .WithMany()
        .HasForeignKey(tp => tp.ParticipantModelId)
        .IsRequired();

Это наводит меня на мысль, что существует несоответствие имен свойств, которое доставляет все проблемы.

0 голосов
/ 04 августа 2020

Дело в том, что у вас есть набор внешних ключей, которые также служат составным ключом для этой таблицы. Фреймворк Entity должен найти способ разрешить некоторые споры об именах. Вы можете явно добавить аннотации данных к модели, чтобы устранить эту проблему.

[ForeignKey("ThreadModel")]
public int ThreadModelId { get; private set; }

А также для другого свойства Почему бы не заявить о своих отношениях, добавив

//...
.WithMany(x => x.ThreadsParticipants)
//...
...