Объясните как правильно применять паттерн Repository с Entity Framework?

Почему нельзя использовать шаблон Repository для работы с несколькими сущностями сразу, зачем нужно делать свой repository на каждую сущность? В чем преимущество и удобство такого подхода?
Например у меня есть пользователь и история его действий, почему просто не добавить метод GetUserWithHistory(int userId) и получать сразу нужную структуру двнных? Тоже и с сохранением. Нужно сохранить новые значения пользователя и записать в историю, получается нужно вызвать операции 2х репозитариев и как-то скоординировать сохранение, что бы откатить при сбое. Как решается эта проблема?
  • Вопрос задан
  • 3221 просмотр
Пригласить эксперта
Ответы на вопрос 4
Fesor
@Fesor
Full-stack developer (Symfony, Angular)
зачем нужно делать свой repository на каждую сущность


Не на каждую сущность а только для сущностей, которые выступают корнями агрегатов сущностей. Ну то есть если у вас есть сущность Product и ProductImage к примеру, то репозиторий вы делаете только для продуктов.

Почему нельзя использовать шаблон Repository для работы с несколькими сущностями сразу


Потому что репозиторий представляет некую штуку, которая отвечает за хранение вещей. Например представьте что репозиторий это полка. У вас есть полка для одних штук, полка для других.

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

И для каждой сущности будут свои правила как и кто может их где хранить. Банальное соблюдение принципа единой ответственности и разделения обязанностей.
Ответ написан
Комментировать
Репозиторий - Это обертка над коллекцией элементов в памяти. Нужны методы Add, Remove, Get(id), GetAll, Find(predicate). Здесь не должно быть методов сохранить, редактировать т.к. для этого нам достаточно просто взять элемент из коллекции и изменить его. Репозиторий не должен знать о базе данных.

Unit of work - Представляет список объектов изменных бизнес транзакциями, координирует запись этих изменений.

Если просто взять элемент недостаточно - делают сервис, который уже знает что и с чем и как сохранять. Не надо делать репозитории для каждой сущности, достаточно 1-го Generic.

https://www.youtube.com/watch?v=rtXpYpZdOzM
https://www.youtube.com/watch?v=QwwfTWMrM9k

Другой подход это DDD, в нем нет репозиториев и unitofwork. Но его сложнее делать и не сразу доходит.
Ответ написан
DarkRaven
@DarkRaven
разработка программного обеспечения
Репозиторий дает одинаковый набор общих API, таких как :
  • IEnumerable<TModel> GetModels();
  • TModel GetModelByID(int modelId);
  • void InsertModel(TModel model);
  • void DeleteModel(int modelID);
  • void UpdateModel(TModel model);
  • void Save();


IEnumerable<TModel> GetModels(); иногда меняется на IQueryable<TModel>GetModels(), тем более в данном примере это более правильно (так как GetModels не имеет параметров, то материализация должна быть в самый последний момент).

Тоже и с сохранением. Нужно сохранить новые значения пользователя и записать в историю, получается нужно вызвать операции 2х репозитариев и как-то скоординировать сохранение, что бы откатить при сбое. Как решается эта проблема?


Это решается с помощью сервисов или Unit of Work, которые построены вокруг объединения репозиториев, связанных единой бизнес-логикой, единого экземпляра контекста, единой транзации где нужно и т.п.

Пример всего этого добра можно глянуть, к примеру, вот тут: https://www.asp.net/mvc/overview/older-versions/ge...

Статейка старенькая, но для общего понимания пойдет. Но самая соль не в этом. Соль ситуации в том, что EF сам по себе UoW, а его DbSet-ы - это репозитории. Соответственно, вам нужны репозитории лишь в том случае, если вы желаете поддержку работы с несколькими, назовем это, бакэндами. В данном конкретном случае бакэендами могут быть:
  • EF
  • NHibernate
  • Linq2db
  • SqlClient/Npgsql/MySQL/etс (тут сложнее и потребуется поработать)
Ответ написан
Комментировать
Valeriy1991
@Valeriy1991
Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
Добрый день! Думаю, очень похожий вопрос: Я не умею готовить репозиторий или он просто не очень?
От себя. Лепить репозитории на каждую сущность выгодно, как мне кажется, только когда этих сущностей раз-два-три и закончились, а проект никогда не будет сопровождаться. В enterprise-решениях следование принципу "1 репозиторий на 1 сущность" приведет к сложностям сопровождения и масштабируемости приложения.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы