Организационно, где я должен поставить общие запросы при использовании Entity Framework Code First?
Я выкладываю новый слой данных, используя EF 4.1 Code First, переходя со старого слоя данных homebrew.
Я установил две сборки, одну для моего контекста и одну для всех первых классов кода POCO.
У меня есть бизнес-логика, например, запрос к одной таблице (или нескольким таблицам), которая используется в нескольких разных местах. Где я должен положить это?
Он не может входить в класс POCO, потому что он объединяет пару таблиц и поэтому нуждается в контексте. Это может идти в контексте, но этот контекст станет раздутым с сотнями неорганизованных запросов. Существует ли общая схема или схема всей бизнес-логики?
3 ответа
Похоже, что шаблон хранилища - это решение для всего... Репозиторий - это не серебряная пуля!
Я использую шаблон репозитория с EF каждый день, потому что когда я начал свой текущий проект несколько месяцев назад, он выглядел как рекомендуемое решение. Мои выводы:
- Хранилище значительно усложняет взаимодействие с EF. Просто просмотрите вопросы, связанные с тегами EF, и вы увидите, какие сложности нужно решать непосредственно в контексте, отслеживании изменений и т. Д.
- Универсальный репозиторий - это то, что работает для операций CRUD, но не для реальных сценариев DDD. Как только ваш репозиторий работает с агрегатными корнями (DDD), общий подход не работает.
- Модульное тестирование не работает вообще, потому что общая идея, что вы будете имитировать репозиторий и тестировать свой верхний уровень без зависимостей от EF, и база данных завершится неудачно, как только вы выставите
IQueryable
, Linq-to-entity является лишь подмножеством Linq-to-objects, и mock не обрабатывает ссылочную целостность так много раз, что я видел зеленые модульные тесты и исключения во время выполнения. Правильный подход к тестированию с EF - это интеграционные тесты. Репозиторий Mocking предназначен только для тестирования реальной бизнес-логики, не связанной с доступом к данным. Если у вас нет интеграционного теста для доступа бизнес-метода или к сохранению данных, вы его не тестировали. - Разоблачение специализированных методов, таких как GetByXXX, просто шаг назад. Большинство из этих методов используются только один раз. Вы закончите с кодом, похожим на репозитории, используемые для упаковки вызовов хранимых процедур. Многим разработчикам нравится ORM только потому, что они могут избежать такой жесткой архитектуры.
Сам EF уже предлагает шаблон хранилища - DbSet
а также ObjectSet
репозитории и DbContext
а также ObjectContext
Единица работ. Так что, по моему мнению, шаблон репозитория чрезмерно используется. Это может быть полезно в больших проектах, где вам нужна строгая многоуровневость, или в случае размещения дополнительной логики для ее методов. Использование репозитория только потому, что вы хотите обернуть доступ к EF, часто является бесполезным кодом и просто дополнительным уровнем сложности.
Таким же образом вы можете создавать повторно используемые методы, определяющие ваши запросы.
Я бы использовал Шаблон репозитория. Ниже приведен пример использования кода EF и MVC Entity Framework 4 CTP 4 / CTP 5 Общий шаблон репозитория и модульное тестирование
Вот некоторые хорошие чтения по шаблону:
- http://www.martinfowler.com/eaaCatalog/repository.html
- http://msdn.microsoft.com/en-us/library/ff649690.aspx
- http://www.devx.com/dotnet/Article/33695/0/page/5
Также может быть хорошей идеей взглянуть на Domain Driven Design (DDD), так как вы начинаете с доменной модели.
Некоторые хорошие чтения на DDD:
Если вы используете EF непосредственно в бизнес-методах (службы уровня домена и службы уровня приложения), то вы не изолируете уровень модели домена от технологий инфраструктуры (в данном случае EF). Это один из принципов DDD. у вас, вероятно, должен быть один репозиторий на агрегат.
Для получения дополнительной информации о DDD, см.:
Книга Эрика Эванса: http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215