Ответ вслух Middle Дженерики обновлено

Обобщённый репозиторий: за и против

Вопрос

Нужен ли в проекте на EF Core обобщённый IRepository<T>? Как бы вы его спроектировали?

Попробуйте сами

Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.

Показать ответ и разбор

Коротко

Технически сделать просто: interface IRepository<T where T : class, IEntity с методами GetById, Add, Remove, а реализация поверх DbSet<T. Ограничение на IEntity даёт доступ к Id.

Что должно прозвучать в ответе

  • Ограничения where T : class, IEntity для доступа к Id

  • DbSet<T> и DbContext уже реализуют репозиторий и единицу работы

  • Обобщённый репозиторий часто прячет IQueryable или наоборот течёт им

  • Специфичные запросы лучше в доменных репозиториях или query-объектах

  • Плюс: единая точка для тестов, кеша, мягкого удаления

Что могут спросить следом

  • Как сделать мягкое удаление без репозитория?
  • Что вернёт метод репозитория: IQueryable или IReadOnlyList?

Разбор

Технически сделать просто: interface IRepository<T> where T : class, IEntity с методами GetById, Add, Remove, а реализация поверх DbSet<T>. Ограничение на IEntity даёт доступ к Id.

Но я спрошу, зачем он нужен. DbContext уже реализует паттерн единицы работы, а DbSet<T> это репозиторий. Обобщённая обёртка часто либо возвращает IQueryable, и тогда абстракция протекает, либо прячет его, и тогда для каждого нового запроса приходится добавлять метод или тянуть все записи в память.

Поэтому я предпочитаю специфичные репозитории под агрегаты, где методы названы по смыслу: GetActiveOrdersForCustomer. Сквозные вещи вроде мягкого удаления и мультиарендности решаю глобальными фильтрами запросов EF Core. Обобщённый репозиторий оправдан, если команда договорилась о нём ради единообразия и тестов, но тогда я возвращаю материализованные IReadOnlyList, а не IQueryable.

Ответьте сами, а не прочитайте

В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.