О «принадлежащих» типах в ядре EF

#c# #entity-framework #entity-framework-core #.net-5 #ef-core-5.0

#c# #сущность-фреймворк #entity-framework-core #.net-5 #ef-core-5.0

Вопрос:

В моем проекте я использую конфигурацию EF Core fluent, сначала код. Я немного прочитал о принадлежащих типах, но ситуация, описанная ниже, мне не совсем понятна:

Предположим, у меня есть Project сущность и ProjectType .
Должен ли я сопоставить это свойство как :

Entity<Project>.HasOne<ProjectType>(); или , скорее , как
Entity<Project>.OwnsOne<ProjectType>();

ProjectType Объект должен быть сопоставлен с таблицей ProjectType(ProjectTypeId, Name, Description)

Как я читал, они

«типы, которые могут появляться только в навигационных свойствах других типов сущностей. Они называются типами принадлежащих объектов. Объект, содержащий принадлежащий тип объекта, является его владельцем. Принадлежащие компании по сути являются частью владельца и не могут существовать без него «.

В моем случае

« ProjectType может появляться только в навигационных свойствах типа Project объекта. ProjectType по сути, является частью Project и не может существовать без него»… однако для того, чтобы создать отдельную таблицу, как я понял, мне нужно использовать HasOne , а не OwnsOne … было бы здорово, если бы кто-нибудь лучше объяснил эту идею. Большое спасибо.

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

1. Я считаю, что первый создаст отдельную таблицу, а второй — нет.

2. @bolkay смотрите Мое обновление OP; кажется, мой ProjectType является принадлежащим типом по определению MS, но, похоже, его не следует использовать в коде…

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

4. @GertArnold Я не вижу проблемы. во всех проектах Id в качестве ссылки используется тип проекта, а не имя.

5. Когда тип проекта является принадлежащим типом, его имя находится в таблице проекта.

Ответ №1:

ProjectTypes звучат как справочная таблица, которую в противном случае можно было бы изменять в течение срока службы приложения, например, с помощью роли системного администратора. Использование нового «Owns» — это соглашение, помогающее применять такие концепции, как композиция, зависящая от типа, и связывание таблиц в реляционной модели данных.

Лучший пример для композиции: допустим, у вас есть проект, и в рамках проекта есть некоторые детали, которые довольно велики и редко используются. Такие вещи, как изображение или другие двоичные данные, или, возможно, какой-то большой текст. Наличие этих деталей BLOB / CLOB внутри таблицы Project может привести к катастрофе при извлечении проекта или многих проектов, поэтому вы нормализуете их в отдельную связанную таблицу с именем ProjectDetails или, возможно, в несколько связанных таблиц. Таким образом, по большей части, когда вы работаете с Project этими объектами и загружаете их, вам не нужно беспокоиться о том, чтобы постоянно извлекать эти большие поля, вы можете ссылаться на ProjectDetails для включения только тогда, когда это действительно необходимо. Поскольку ProjectDetails на самом деле не служит никакой цели сам по себе, ему не нужен DbSet или что-то подобное, поэтому мы можем установить связь между Project OwnsOne и ProjectDetails.

С другой стороны, у ProjectType потенциально может быть DbSet для создания новых типов проектов в процессе настройки приложения. Вы также можете захотеть связать другие детали, связанные с проектом, на основе типа проекта. В этом случае для Project было бы более разумно HasOne использовать ProjectType. У нас может быть DbSet типов проектов для управления, и другие объекты также могут фильтроваться по типу проекта, этапам / фазам проекта и т. Д.

Насколько схема базы данных проходит между Owns и Has , разницы нет. Речь идет исключительно о том, как EF DbContext будет ожидать работы с объектами.

Другими распространенными примерами использования Owns являются таблицы ссылок. Например, у вас есть таблица адресов, которая является общей для заказов, клиентов и т. Д. Ни один из них не «владеет» адресами, но они владеют своей таблицей ссылок: Order владеет OrderAddress, Customer владеет CustomerAddress. Эти объекты «Имеют» адрес. Мы все равно можем захотеть просмотреть адреса, поскольку они представляют физические местоположения, и есть разница между связыванием заказа и т. Д. в другое местоположение и «корректировка» сведений, записанных для физического местоположения. (Т.е. Исправление названия улицы или муниципалитета) Нет необходимости когда-либо иметь дело с OrderAddresses или CustomerAddresses за пределами области Order или Customer соответственно.

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

1. Спасибо, что внесли некоторую ясность в тему. Жаль, что в документах отсутствуют такие важные детали (ссылка в OP). Потому что мой ProjectType формально соответствует определению документов owned type .

2. «Что касается схемы базы данных между Owns и Has, разницы нет. Речь идет исключительно о том, как EF DbContext будет ожидать работы с объектами» Это правда? Я думал Owns , что вставил бы дочерний элемент внутри родительского, тогда Has как создал бы новую таблицу.

3. С взаимно однозначными отношениями он может быть встроен в основную таблицу (по-видимому, это поведение по умолчанию) или в отдельную таблицу. Для «один ко многим» используется отдельная таблица. Я не могу придумать вариант использования, в котором я хотел бы встроить принадлежащий объект в ту же таблицу, кроме, возможно, столбца JSON, если это вообще поддерживается. Более распространенный сценарий, с которым я сталкиваюсь, — использовать Has / Owns для включения разделения таблиц. 🙂 Но, безусловно, это хороший момент для рассмотрения.