Переход от «один ко многим» к «многие ко многим» с новым EF Core 5.0

У меня есть проект ASP.NET Core 5 (перенесенный из ASP.NET Core 3.1). В проекте используется EF Core.

EF Core 5 имеет встроенную поддержку «многие ко многим». Основная причина, по которой я впервые перешел с 3.1 на 5.0.

Теперь в моем проекте есть отношение «один ко многим», которое я хочу преобразовать в «многие ко многим».

Возможна ли такая миграция отношений?

Текущий код:

    public class File
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    [Key]
    public int Id { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid UniqueId { get; set; }

    public int RecordId { get; set; }

    public virtual Record Record { get; set; }
    // ...
}


public class Record
{
    [Key]
    public int Id { get; set; }

    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid UniqueId { get; set; }

    public virtual ICollection<File> Files { get; set; }
}


  public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
  {

    public DbSet<File> Files { get; set; }
    public DbSet<Record> Records { get; set; }

     protected override void OnModelCreating(ModelBuilder builder)
     {
         base.OnModelCreating(builder);

         builder.Entity<Record>().ToTable("Record");

         // for creating GUIDs   
         builder.Entity<Record>().Property(x => x.UniqueId).HasDefaultValueSql("newid()");
         builder.Entity<File>().Property(x => x.UniqueId).HasDefaultValueSql("newid()");
     }

  }

В приведенном выше коде вы можете видеть, что запись имеет ноль, один или несколько файлов. С файлом связана только одна запись.

Я хотел бы изменить это так, чтобы один файл мог быть назначен нескольким записям (таким образом я уменьшаю количество дубликатов файлов и уменьшаю дисковое пространство, улучшаю сетевой трафик за счет увеличения количества обращений к кешу и т. д.).

В классе File я просто удаляю эти строки кода:

public int RecordId { get; set; }

public virtual Record Record { get; set; }

и заменить его этой строкой ниже?

public virtual ICollection<Record> Records { get; set; }

Я бы не хотел уничтожать и вручную изменять многие тысячи взаимосвязей файловых записей... или нарушать их.


person juFo    schedule 21.01.2021    source источник


Ответы (1)


  1. общественный интервал RecordId { получить; установлен; } // Не удалять

    публичная виртуальная запись Record { get; установлен; }` изменить на

    общедоступные виртуальные записи ICollection { get; установлен; }

2.добавить сущность

public class FileRecord
{
    public int FileId { get; set; }
    public File File { get; set; }

    public int RecordId { get; set; }
    public Record Record { get; set; }
}
  1. общедоступные DbSet FileRecords { получить; установлен; }

entity.HasOne(d => d.Record)
                .WithMany(p => p.Files)
                .HasForeignKey(d => d.RecordId);

Изменить на

entity.HasMany(d => d. Records)
                .WithMany(p => p.Files)
                .UsingEntity<FileRecord>(
                j => j
                .HasOne(pt => pt.Record)
                .WithMany()
                .HasForeignKey(pt => pt.RecordId),
            j => j
                .HasOne(pt => pt.File)
                .WithMany()
                .HasForeignKey(pt => pt.FileId),
            j =>
            {
                j.HasKey(t => new { t.TeamId, t.RecordId });
            });

5.Добавить-миграцию

In created migration file add
        protected override void Up(MigrationBuilder migrationBuilder)
{
    //……
    migrationBuilder.Sql("INSERT INTO FileRecords (FileId, RecordId) SELECT Files.Id, Files.RecordId FROM Files");
}

6.Проверить все в порядке, удалить public int RecordId { get; set; } в классе File и добавить-миграцию

person Rif Yarullin    schedule 17.02.2021
comment
Отличный @Риф Яруллин! На самом деле я сделал это вручную, экспортировав данные, удалив таблицу, снова добавив ее с помощью миграции с корректирующим отношением и снова вставив данные с помощью операторов вставки сервера sql. так как я не был уверен, смогу ли я использовать файл migrationbuilder.sql. Спасибо за указание на это. Действительно думаю, что это может быть полезно и для других! - person juFo; 18.02.2021