Comments 26
По мне, так как раз первый способ более красивый и читабельный. Насчет "недостаточно гибкий" возможно.
Если первый пример я просмотрел краем глаза и вопросов не осталось, то остальные - пришлось вчитываться и вникать.
Спасибо большое за фидбек!
Использую в работе только второй способ IEntityTypeConfiguration<> это решение оказалось максимально гибким. И вот почему.
Аннотационное описание, хорошо тем что она вещь "сама в себе". Но мы жестко привязываем описание к модели, и если хотим передать ту же модель в
клиентскуюдругую часть приложения, то передаем и сведения о полях базы их граничениях.Fluent описание в OnModelCreating привязано к конкретному dbContext
В IEntityTypeConfiguration<> мы достаточно свободны, чтобы теоретически вынести все компоненты: модель, контекст, и описание в разные библиотеки, и потом свободно их комбинировать, и повышает переиспользование кода.
Ну и из очевидного - мы легко можем заменить реализацию интерфейса, а в других случаях это вызовет небольшие сложности.
Если у Вас мнолит, тогда да, использовать атрибуты допустимо. Но в микросервисной архитектуре, где модельки лежат в Domain'е, а работа с бд в Infrastructure/Persistence, то это будет грубым нарушением. А если вспомнить чистую архитектуру дяди Боба, то там места атрибутам нету вообще. Так что тут скорее надо сперва принимать решение какую архитектуру Вы будете использовать для проекта, а затем уже использовать/не использовать атрибуты. Лично я стараюсь во всех своих микросервисах использовать крайний вариант
Главное единообразие, а то посмотришь на проектах - все три стиля вперемешку, ничего кроме раздражения не вызывает.
Предпочитаю FluentApi с интерфейсом. Как по мне более гибкий и понятный. Плюс с учётом, что у нас часто это доменные сущности, а не просто POCO, то вообще аттрибуты там нафиг не нужны
Безусловно. Всё на своих местах и не размазано по коду. В контексте DDD лучший выбор.
Ну как правило, слои разделяют, и, соответственно - доменные сущности будут "жить" в слое для реализации доменной логики и ничего не знать о деталях реализации работы с БД. А вот наши классы-сущности в слое доступа к данным, так что и атрибуты подойдут, если не много объектов. Но в любом случае - спасибо за столь ёмкую обратную связь!
Это тема для следующей статьи, кстати)
Так доменная сущность в любом случае не будет знать о реализации работы с БД. Просто с помощью Fluent можно гибко настроить маппинг сразу из базы, без всяких промежуточных классов.
А вообще - это чисто вкусовщина, здесь нет какого-то однозначно правильного решения и смысла спорить тоже.
Выглядит не очень красиво, согласитесь?
Не соглашусь. По сравнению с fluent, гораздо локаничнее, да и нагляднее.
Ну а если ещё добавить summary к каждому свойству, и свойств будет более 2-3 и настроить маппинг на поля объектов БД надо будет более тонко? Например:
[Table("Cars")]
public class CarEntity
{
/// <summary>That represents unique identifier</summary>
[Key]
public Guid Id { get; set; }
/// <summary>That represents make of vehicle and null input not allowed</summary>
[Column("Make", TypeName = "varchar2")]
[MaxLength(16)]
[Required]
public string Make { get; set; }
/// <summary>That represents model of vehicle and null input is not allowed</summary>
[Column("Model", TypeName = "varchar2")]
[MaxLength(26)]
[Required]
public string Model { get; set; }
/// <summary>That represents production year of vehicle</summary>
[Column("Year")]
public int ModelYear { get; set; }
/// <summary>That represents VIN (vehicle identifier) of vehicle and null input is not allowed</summary>
[Column("VIN", TypeName = "varchar2")]
[MaxLength(14)]
[Required]
public string Vin { get; set; }
/// <summary>That represents color of vehicle</summary>
[Column("Color", TypeName = "varchar2")]
[MaxLength(16)]
public string Color { get; set; }
}
Уже не так читабельно (как по мне), согласитесь?
Если такая беда с маппингом на поля таблицы, то что аттрибуты, что fluent - всё одинаково говнисто будет выглядеть.
FluentAPI даёт гораздо больше возможностей в плане настроек, но ограничения лично мне удобней искать в классе.
Как сказали несколькими комментариями выше - это всё вкусовщина, особенно на текущих примерах. Разницу по функциональности способов мы рассмотрим в следующих статьях.
но ограничения лично мне удобней искать в классе.
Это дело привычки. Информацию по конфигурированию БД, так же, удобно искать там, где лежит эта конфигурация. Можно ведь ограничения отдельно указать в классе конфигурации. Отделить пустой строкой от других настроек.
А вообще, если задуматься над тем, зачем вам смотреть ограничения, можно предположить, что вы начинаете приложение с базы данных. Иначе вы бы смотрели ограничения в документации (в Open API или любой другой, хоть в свободной форме) или в настройке валидации для полей ввода (или для ДТО).
Начинать с БД это не плохо, но отделяет разработку от предметной области. Типа мы затачиваем предметку под ограничения БД, а не наоборот.
Тут несколько пустых строк добавить и уже лучше станет.
И нет, на FluentAPI вы более читаемо не сможете сделать, там будет такая же мешанина.
где sealed
-_-
Выглядит не очень красиво, согласитесь?
Если это слой доступа к данным, то выглядит это прекрасно. В одном месте и объявление типов данных, и маппинги.
Возникает вопрос - а должны ли сущности EF протекать в слой бизнес-логики? Или EF POCO объекты должны маппиться в объекты домена, у которых будет и логика, и поведение, но не будет ненужных на этом уровне аттрибутов-аннотаций, связанных с EF.
Суть не в частоте использования, а потенциальных проблемах которые могут появится при подобной потребности.
Говорил что ему сильно проще получается.
Как вы наверно знаете, в ASPMVC есть особые ограничение на тип передаваемых аргументов между экшнами. Мой бывший коллега (привет Сергей) чтобы передать коллекцию целочисленных элементов, делал конкатенацию в строку, передавал ее в целевой экшн, а потом делил по разделителю и переводил обратно в int. Правильно ли это было? Нет, для этого в MVC были свои инструменты.. с моей точки зрения это индусский говнокод, который накладывал ограничения еще и на клиентскую часть, но ему так было удобно и "сильно проще".
мне не нравится подход не чистых моделей
Конфигурация сущностей в EF Core