Наследование сущностей ASP.NET Core 2.2 и ссылка на БД - PullRequest
1 голос
/ 10 июня 2019

https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-2.2 Объясняет, как расширить идентификатор по умолчанию путем создания подклассов. У меня есть настройки кода, как объяснено, и это работает, но теперь я хотел бы расширить его, потому что в зависимости от роли пользователя существуют различные атрибуты. Например. ApplicationUser может иметь избранное, но расширенное ApplicationUser имеет элементы.

Я хотел бы создать больше подклассов ApplicationUser. Это хорошая идея?

Модель - Элемент. ApplicationUser имеет набор элементов и может добавлять их в избранное.

ExtendedApplicationUser наследуется от ApplicationUser и может добавлять экземпляры Element, которые ApplicationUser может избирать.

Что мне делать?

  1. Должен ли я создать роль для ApplicationUser и ExtendedApplicationUser и объявить оба набора в ApplicationUser, без подкласса.
  2. Или я могу создать подкласс ApplicationUser, поместив каждый набор в каждый класс? Моей первой мыслью было бы создать подкласс ApplicationUser, но я не уверен, что вместо этого лучше использовать роли.

Последний вопрос, как мне объявить наборы в сущности ApplicationUser? Я использую HashSet или DbSet?

1 Ответ

2 голосов
/ 10 июня 2019

Да, в общем, наследование - это правильный способ моделирования.Вам нужен один и только один класс, который унаследует от IdentityUser.Это будет ваша база ApplicationUser.Тогда другие типы пользователей будут наследовать от ApplicationUser.

При этом обработка наследования в EF Core оставляет желать лот .В частности, он поддерживает только TPH (таблица на иерархию), также известная как наследование одной таблицы.Другими словами, независимо от того, что вы делаете, у вас всегда будет только одна пользовательская таблица, и все реквизиты для всех типов пользователей должны будут находиться в этой одной таблице.Практически это просто означает, что вы не можете иметь ненулевые свойства в своих подклассах, так как другие подклассы не смогут предоставить значение для них, и вставки в этом случае будут неудачными.Однако это в основном можно смягчить, используя модели представлений и применяя свои бизнес-правила для того, что требуется, а что нет, вместо этого.Вы не получите валидацию на уровне БД, но ввод через формы и тому подобное всегда будет валидирован.

Выше следует упомянуть, учитывая, что вы не можете использовать более подходящие стратегии моделирования баз данных, такие как таблицадля каждого типа (TPT) или типа таблицы для конкретного (TPC) использование наследования является довольно бессмысленным с точки зрения базы данных.Если вам не нужно принудительно указывать в коде, что только определенный набор свойств или другое может быть изменено для определенного типа пользователя, вы можете просто придерживаться одного пользовательского класса.Наличие нескольких типов пользователей не является тривиальным, поэтому необходимо сделать аргумент, чтобы сделать его простым, если только у вас нет острой необходимости поступать иначе.

В частности, легко напутать ввод текста пользователем, если выне осторожноНаследование одной таблицы работает путем добавления столбца дискриминатора, который содержит фактический тип сохраняемого.Другими словами, если вы сохраните ApplicationUser, тогда значением будет «ApplicationUser», или если вы сохраните ExtendedApplicationUser, тогда значением будет «ExtendedApplicationUser».EF использует это значение, чтобы определить, какой тип должен быть создан.Где это сложно - с UserManager<TUser>.Параметр универсального типа, а не то, что передается в методы типа CreateAsync, определяет тип, который будет сохранен.Например, если вы создаете новый файл ExtendedApplicationUser, но сохраняете его с помощью экземпляра UserManager<ApplicationUser>, он будет преобразован в ApplicationUser и затем сохранен, в результате чего «ApplicationUser» будет записан в столбец дискриминатора.Если вам нужно работать с ExtendedApplicationUser, вам понадобится экземпляр UserManager<ExtendedApplicationUser>, и у вас может оказаться несколько таких менеджеров пользователей, каждый для работы с определенным типом пользователя.Таким образом, вам нужно быть осторожным, чтобы использовать правильный диспетчер пользователей для правильного сценария.

Для вашего последнего вопроса ответ - ни тот, ни другой.Свойства коллекции должны быть либо ICollection<TEntity>, либо List<TEntity>.HashSet может использоваться для удовлетворения ICollection<TEntity> при записи в свойство, но не вводите его так.DbSet только для контекста.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...