Как создать несколько внешних ключей из одной таблицы в другую, если таблица 1 содержит несколько полей с fk для одного столбца таблицы 2 - PullRequest
0 голосов
/ 06 апреля 2019

У меня есть таблица «info» с некоторыми полями, которые указывают на столбец «id» таблицы «file_uploads». Также я третья таблица с fk для "file_uploads", давайте назовем его "another_table". Как я могу описать отношения в EF fluent api для использования Linq Join или Include Queries?

InfoRecord {
    public long Id {get; set;}
    public long File1Id {get; set;}
    public long File2Id {get; set;}
    public long File3Id {get; set;}

    public List<FileUploadRecord> Files {get; set;}
}

FileUploadRecord {
    public long Id {get; set;}
    public long Url {get; set;}

    public InfoRecord Info {get; set;}
}

AnotherTableRecord {
    public long Id {get; set;}
    public long ImageId {get; set;}

    public long FileUploadRecord Image { get; set; }
}

Я знаю, что могу создать простой необработанный SQL-запрос с помощью join, и он будет работать, но он не работает с Linq .Include или .Join. Я пытался решить ее разными способами, но EF выдает ошибки о плохих отношениях с ФК.

1 Ответ

0 голосов
/ 07 апреля 2019

Я думаю, вам нужно немного подправить свои модели.Прямо сейчас в таблице InfoRecord есть три столбца, указывающие на таблицу файлов.Проблема в том, что если завтра вам понадобится больше файлов?Добавление большего количества столбцов не является оптимальным.Процесс исправления это то, что называется Нормализация базы данных .

Если InfoRecord требуется «несколько столбцов для указания идентификатора» на FileUpload, у вас есть отношение one-to-many - один InfoRecord может иметь один или несколько файлов.Мы можем добиться нормализации, используя 3 таблицы:

1 - FileUpload (фактические файлы, самая основная сущность. Здесь никаких связей нет.)

public class FileUpload
{
    public long Id { get; set; }

    public string FileName { get; set; }

    public string FilePath { get; set; }
}

2 - InfoRecord - Как вашвопрос, InfoRecord может иметь много файлов:

public class InfoRecord
{
    public long Id { get; set; }

    public string Title { get; set; }

    public ICollection<FileUploadRecord> Files { get; set; }
}

И, наконец, сущность, которая «склеивает» их вместе:

3 - FileUploadRecord - имеет FK к FileUpload и InfoRecord

public class FileUploadRecord
{
    public long Id { get; set; }

    // FK to InfoRecord. Usefull for update scenarious
    // without having to load the whole entity.
    public long InfoRecordId { get; set; }

    public InfoRecord InfoRecord { get; set; }

    // FK To the actual file upload
    public long FileId { get; set; }

    public FileUpload FileUpload { get; set; }
}

Затем вы можете настроить его с помощью FluentAPI следующим образом:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // Configure the Entity that "glues" InfoRecord and FileUploads. 
    // One InfoRecord can have many files, so we need a table to store that relationship.
    modelBuilder.Entity<FileUploadRecord>()
        .HasOne(s => s.InfoRecord)
        .WithMany(g => g.Files)
        .HasForeignKey(s => s.InfoRecordId);

    modelBuilder.Entity<FileUploadRecord>()
        .HasOne(p => p.FileUpload)
        .WithMany()
        .HasForeignKey(p => p.FileId);
}

И запросить с помощью .Include, как вы хотели, легкосейчас.Запрос ниже загружает все InfoRecords с каждым соответствующим файлом.

var recordsWithFiles = context.InfoRecords
                    .Include(p => p.Files)
                    .ThenInclude(p => p.FileUpload);

Вот так будет выглядеть схема БД: enter image description here

Согласно "another_table", это выглядит как простое отношение one-to-oneтаким образом, вы можете просто использовать для него простые EF Core Conventions .Конечно, .Include также работает здесь.

public class AnotherTableRecord
{
    public long Id { get; set; }

    // FK To the actual file upload
    public long ImageId { get; set; }

    public FileUpload Image { get; set; }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...