EF Core 5 — Несколько свойств навигации с одним и тем же (связанным) внешним ключом?

#c# #entity-framework #entity-framework-core #ef-core-5.0

Вопрос:

У меня есть стол, который выглядит примерно так. Связанный идентификатор является основным идентификатором данных, которые будут когда — либо присутствовать только в одной из трех других таблиц (представленных типами 1, 2 и 3- например. Type1 может содержать строку для связанного идентификатора, но Type2 и Type3 не будут). Когда я пытаюсь включить все три сущности для проверки их присутствия, ef core генерирует внутреннее соединение со всеми тремя свойствами навигации, которое возвращает значение null для каждого свойства навигации, поскольку только одна из таблиц содержит данные для соответствующего идентификатора, в то время как другие этого не делают, и поэтому внутреннее соединение со всеми тремя не возвращает результатов. Единственный способ вернуть одно свойство, заданное в соответствующей таблице, — это если соединение является левым соединением, которое не указано в атрибуте внешнего ключа/модели fluent.

Очевидно, что в SQL связанный идентификатор не может быть истинным внешним ключом, но я использую атрибут для пометки свойств навигации. Первичный ключ каждого типа 1, 2 и 3-это связанный идентификатор этой таблицы.

Независимо от того, является ли это правильным дизайном базы данных (используя связанный идентификатор таким образом) — можно ли заставить EF core возвращать эти сущности с помощью левого/внешнего соединения, чтобы запрос мог быть выполнен успешно, или я не должен использовать навигационные свойства в этом контексте, потому что невозможно выполнить запрос без внутреннего соединения? Или есть альтернативный атрибут, который я мог бы/должен использовать для обозначения этой связи? Я бы предпочел не требовать трех отдельных столбцов с внешними ключами для каждой из связанных таблиц (нам не нравится иметь много дополнительных столбцов, которые будут заполнены нулевыми значениями, потому что только один из столбцов будет заполнен).

 public class SomeThing
{
    [Key]
    public Guid PrimaryID { get; set; }

    public Guid RelatedID { get; set; }

    // There is only ever data for one of these types
    [ForeignKey("RelatedID")]
    public virtual Type1 Related1{ get; set; }

    [ForeignKey("RelatedID")]
    public virtual Type2 Related2 { get; set; }

    [ForeignKey("RelatedID")]
    public virtual Type3 Related3 { get; set; }
}
 

Комментарии:

1. В ядре Entity Framework одно свойство внешнего ключа не может участвовать в нескольких отношениях.

2. Да, это действительно подводит итог проблеме. Итак, мой вопрос заключался в том, есть ли аннотация базы данных, которую я могу использовать, или я застрял с ручными соединениями?

3. Я прочитал отредактированный пост. И я должен сказать, что чье-то повествование не всегда передает сообщение должным образом, как оно было задумано, особенно в сообществе разработчиков. Всегда есть вероятность быть неправильно истолкованным. Поэтому было бы лучше, если бы вы могли описать свой сценарий/требование в терминах кода, а не в английских предложениях.

4. Например, 1) » связанный идентификатор может быть основным идентификатором в одной из трех других таблиц » — внешний ключ не настраивается динамически на основе вашего запроса, поэтому вам необходимо создать все три связи. 2) » Только один из них когда — либо будет присутствовать». — это расплывчатое описание. Вы имеете в виду, что в ваших запросах будет присутствовать только одна родительская ссылка LINQ ? 3) » следовательно, внутреннее соединение против всех трех не даст никаких результатов» — но я проверил, и оно возвращает все три в результате. Вы хотели сказать, что это не должно возвращать никакого результата (как вы ожидаете)?

5. Надеюсь, я выразился немного яснее. В моих данных только в одной из связанных таблиц в любой момент времени будет строка, соответствующая соответствующему идентификатору. Из-за того, что внутреннее объединение выполняется во всех трех таблицах (две из которых не дали бы результатов) для заполнения свойств навигации, все они возвращают значение null. Я надеюсь, что это немного яснее. На данный момент мне приходится использовать отдельные соединения с defaultifempty, а затем выбирать свойства, в которых результаты не являются нулевыми.