Создаваемые дубликаты внешних ключей и столбцов для идентификатора EF Core 3.1

Возникла проблема с ef core 3.1, создающим повторяющиеся столбцы для поля идентификатора из другой таблицы. В настоящее время у меня есть сущность ApplicationUser, наследуемая от IdentityUser, и сущность свойства, которая хранит идентификатор ApplicationUser как UserId.

 public class Property
    {
        public Guid PropertyId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public Guid AddressId { get; set; }
        public Address PropertyAddress { get; set; }
        public bool IsHome { get; set; }
        public string UserId { get; set; }
        public ApplicationUser User { get; set; }
    }
public class ApplicationUser : IdentityUser
    {
        public IEnumerable<Property> properties { get; set; }
    }
public class PropertyConfig : IEntityTypeConfiguration<Property>
    {
        public void Configure(EntityTypeBuilder<Property> builder)
        {
            builder.HasKey(p => p.PropertyId);
            builder.HasOne(p => p.PropertyAddress).WithOne();
            builder.HasOne(p => p.User).WithMany(p => p.properties).HasForeignKey(f => f.UserId).OnDelete(DeleteBehavior.Restrict);
        }
    }
 public class ApplicationUserConfig : IEntityTypeConfiguration<ApplicationUser>
    {
        public void Configure(EntityTypeBuilder<ApplicationUser> builder)
        {
            builder.ToTable("User");
            builder.HasKey(p => p.Id);
            builder.HasMany<Property>().WithOne(p => p.User).HasForeignKey(f => f.UserId);
        }
    }

Выше мои классы, и я выполнил миграцию, которая создает эту таблицу для свойства.

migrationBuilder.CreateTable(
                name: "Property",
                columns: table => new
                {
                    PropertyId = table.Column<Guid>(nullable: false),
                    Name = table.Column<string>(nullable: true),
                    Description = table.Column<string>(nullable: true),
                    AddressId = table.Column<Guid>(nullable: false),
                    IsHome = table.Column<bool>(nullable: false),
                    UserId = table.Column<string>(nullable: true),
                    ApplicationUserId = table.Column<string>(nullable: true)
                },
                constraints: table =>
                {
                    table.PrimaryKey("PK_Property", x => x.PropertyId);
                    table.ForeignKey(
                        name: "FK_Property_Address_AddressId",
                        column: x => x.AddressId,
                        principalTable: "Address",
                        principalColumn: "AddressId",
                        onDelete: ReferentialAction.Cascade);
                    table.ForeignKey(
                        name: "FK_Property_User_ApplicationUserId",
                        column: x => x.ApplicationUserId,
                        principalTable: "User",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                    table.ForeignKey(
                        name: "FK_Property_User_UserId",
                        column: x => x.UserId,
                        principalTable: "User",
                        principalColumn: "Id",
                        onDelete: ReferentialAction.Restrict);
                });

Как видите, создается правильный столбец UserId и внешний ключ. но он также создает ApplicationUserId, и я не могу понять, что его вызывает.

Любая идея?

Любая помощь будет оценена по достоинству.


person Adam Wilson    schedule 09.07.2020    source источник
comment
Вы пробовали HasMany(u => u.properties)?   -  person Aluan Haddad    schedule 09.07.2020
comment
@AluanHaddad спасибо, что разобрал проблему с такой маленькой ошибкой за 2 часа головной боли. если вы дадите ответ, я отмечу его как полезный для кого-то, кого это поймает.   -  person Adam Wilson    schedule 09.07.2020


Ответы (2)


В вашей свободной конфигурации API

public void Configure(EntityTypeBuilder<ApplicationUser> builder) {
    builder.HasMany<Property>()
        .WithOne(p => p.User)
        .HasForeignKey(f => f.UserId);
}

Вы просто говорите, что между сущностями ApplicationUser и Property существует связь «один ко многим», но не о том, какие члены задействованы со стороны многие. Действительно, между Property ApplicationUser может быть несколько ассоциаций.

Чтобы заставить его работать, укажите участников, задействованных на обоих концах, настроив вашу конфигурацию следующим образом

public void Configure(EntityTypeBuilder<ApplicationUser> builder) {
    builder.HasMany(u => u.properties)
        .WithOne(p => p.User)
        .HasForeignKey(f => f.UserId);
}
person Aluan Haddad    schedule 09.07.2020

Это потому, что у вас есть оба:

  public string UserId { get; set; }
  public ApplicationUser User { get; set; }

Если вы не хотите User ссылаться на User таблицу, вам придется ее проигнорировать. Что-то вроде этого (не могу вспомнить, точный ли это синтаксис)

   builder.Property(p => p.User).Ignore();

Но это означает, что когда вы извлекаете Property из контекста, User будет нулевым. Также, если вы прикрепите ApplicationUser к Property, а затем сохраните свойство - ни User, ни отношение не будут записаны в базу данных, и вам нужно будет установить UserId вручную.

person LLL    schedule 09.07.2020
comment
но, насколько я понимаю, это должно быть разрешено, как показано здесь: learnentityframeworkcore.com/conventions/ - person Adam Wilson; 09.07.2020