Pull to refresh

Comments 26

По мне, так как раз первый способ более красивый и читабельный. Насчет "недостаточно гибкий" возможно.

Если первый пример я просмотрел краем глаза и вопросов не осталось, то остальные - пришлось вчитываться и вникать.

Использую в работе только второй способ IEntityTypeConfiguration<> это решение оказалось максимально гибким. И вот почему.

  • Аннотационное описание, хорошо тем что она вещь "сама в себе". Но мы жестко привязываем описание к модели, и если хотим передать ту же модель в клиентскую другую часть приложения, то передаем и сведения о полях базы их граничениях.

  • Fluent описание в OnModelCreating привязано к конкретному dbContext

  • В IEntityTypeConfiguration<> мы достаточно свободны, чтобы теоретически вынести все компоненты: модель, контекст, и описание в разные библиотеки, и потом свободно их комбинировать, и повышает переиспользование кода.

  • Ну и из очевидного - мы легко можем заменить реализацию интерфейса, а в других случаях это вызовет небольшие сложности.

Если у Вас мнолит, тогда да, использовать атрибуты допустимо. Но в микросервисной архитектуре, где модельки лежат в Domain'е, а работа с бд в Infrastructure/Persistence, то это будет грубым нарушением. А если вспомнить чистую архитектуру дяди Боба, то там места атрибутам нету вообще. Так что тут скорее надо сперва принимать решение какую архитектуру Вы будете использовать для проекта, а затем уже использовать/не использовать атрибуты. Лично я стараюсь во всех своих микросервисах использовать крайний вариант

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

Главное единообразие, а то посмотришь на проектах - все три стиля вперемешку, ничего кроме раздражения не вызывает.

Предпочитаю 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 вы более читаемо не сможете сделать, там будет такая же мешанина.

Выглядит не очень красиво, согласитесь?

Если это слой доступа к данным, то выглядит это прекрасно. В одном месте и объявление типов данных, и маппинги.

Возникает вопрос - а должны ли сущности EF протекать в слой бизнес-логики? Или EF POCO объекты должны маппиться в объекты домена, у которых будет и логика, и поведение, но не будет ненужных на этом уровне аттрибутов-аннотаций, связанных с EF.

Мне больше по душе, чтобы слои были строго разделены между собой и являлись слабосвязанными. Для меня однозначно - POCO-объекты должны маппиться в объекты домена. Более глубоко данного вопроса мы коснёмся в следующей статье.
Спасибо за фидбек!

UFO just landed and posted this here

Суть не в частоте использования, а потенциальных проблемах которые могут появится при подобной потребности.

Говорил что ему сильно проще получается.

Как вы наверно знаете, в ASPMVC есть особые ограничение на тип передаваемых аргументов между экшнами. Мой бывший коллега (привет Сергей) чтобы передать коллекцию целочисленных элементов, делал конкатенацию в строку, передавал ее в целевой экшн, а потом делил по разделителю и переводил обратно в int. Правильно ли это было? Нет, для этого в MVC были свои инструменты.. с моей точки зрения это индусский говнокод, который накладывал ограничения еще и на клиентскую часть, но ему так было удобно и "сильно проще".

UFO just landed and posted this here

Вы хоть немного за контекстом следите, я ни слова не говорил о генерации.

UFO just landed and posted this here

мне не нравится подход не чистых моделей

Sign up to leave a comment.

Articles