Подтвердить что ты не робот

Использование шаблона репозитория для поддержки нескольких поставщиков

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

Например, предположим, что я хочу использовать Entity Framework для своего приложения. Тем не менее, я также хочу иметь набор тестовых данных, реализованных в жестко кодированных списках. Я хотел бы иметь набор интерфейсов (IUserRepository, IProductRepository и т.д.), Чтобы не говорить о более общем IRepository <T> на данный момент), что оба подхода могут создать экземпляр. Затем, используя (скажем) инструмент Injection Dependency, такой как Ninject или Castle Windsor, я могу переключаться между провайдером инфраструктуры сущностей (доступ к фактической базе данных) и поставщиком тестов (доступ к спискам).

В двух словах, здесь проблема:

- Если вы собираетесь использовать Entity Framework, вы хотите, чтобы ваши репозитории возвращали IQueryable <SomeType> .

- Если вы собираетесь использовать списки с жестким кодированием, вы НЕ хотите, чтобы ваши репозитории возвращали IQueryable, потому что он очень сильно добавляет накладные расходы, а плюс Linq to Entities значительно отличается от Linq to Objects, что вызывает много головных болей в коде, который является общим для обоих поставщиков.

Другими словами, я нашел, что лучший подход изолирует весь EF-зависимый код в репозиториях, так что сами репозитории возвращают IEnumerable или IList или некоторые из них - тогда как EF, так и некоторые другие технологии могут использовать один и тот же хранилища. Таким образом, все IQueryable будет содержаться В РЕГИОНАХ EF. Таким образом, вы можете использовать Linq для Entities с репозиториями EF и Linq для объектов с тестовыми репозиториями.

Однако этот подход ставит огромную часть бизнес-логики в репозитории и приводит к значительному дублированному коду - логика должна дублироваться в каждом из репозиториев, даже если реализации несколько отличаются.

Вся идея репозиториев как этого слоя, который очень тонкий и просто соединяется с базой данных, затем теряется - репозитории являются "репозиториями" бизнес-логики, а также связью хранилища данных. Вы не можете просто найти, сохранить, обновить и т.д.

Мне не удалось устранить это несоответствие между необходимостью изолировать код, зависящий от провайдера, и иметь бизнес-логику в централизованном месте.

Любые идеи? Если бы кто-нибудь мог указать мне пример реализации, который затрагивает эту проблему, я был бы весьма признателен. (Я много читал, но не могу найти ничего, что конкретно говорит об этих проблемах.)

UPDATE:

Я думаю, что я начинаю чувствовать, что, возможно, нет репозиториев, которые могут быть заменены для разных поставщиков, - что, если вы собираетесь использовать Entity Framework, например, вам просто нужно посвятить все свое приложение к платформе Entity Framework. Единичные тесты? Я борюсь с этим. Моя практика заключается в том, чтобы настроить отдельный репозиторий с жестко закодированными данными и использовать его для модульного тестирования, а также для тестирования самого приложения до того, как база данных будет настроена. Я думаю, мне придется искать другое решение, возможно, какой-то насмешливый инструмент.

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

4b9b3361

Ответ 1

Что я могу сказать? Добро пожаловать в клуб...

То, что вы нашли, - это проблема, достигнутая многими разработчиками, которые следовали "буму хранилища" с EFv4. Да, это проблема, и проблема действительно сложная. Я обсуждал это несколько раз:

Отдельная тема - почему использовать репозитории:

В принципе, предложенный вами способ - это решение, но действительно ли оно вам нужно? По моему мнению, результатом является не репозиторий, а объект доступа к данным (DAO), предоставляющий множество методов доступа. Определение репозитория Мартин Фаулер:

Репозиторий посредничает между слоев домена и данных, действующих как объект домена в памяти коллекция. Конструкция клиентских объектов спецификаций запросов декларативно и отправьте их в Репозиторий для удовлетворение. Объекты могут быть добавлены к и удаляется из репозитория, так как они могут из простой коллекции объекты и код отображения инкапсулированный Репозиторием, будет выполнять соответствующие операции за кулисами. Концептуально Репозиторий инкапсулирует набор объекты сохранялись в хранилище данных и операции, выполняемые над ними, обеспечивая более объектно-ориентированное представление слоя устойчивости. вместилище также поддерживает цель достижение чистого разделения и односторонняя зависимость между доменом и слоев отображения данных.

Я считаю, что публикация IQueryable выполняется в 100 раз лучше, чем создание общедоступного интерфейса, подобного репозиториям из эпохи хранимых процедур - одному методу доступа к хранимой процедуре (фиксированный запрос).

Проблема может быть суммирована по правилу нечеткой абстракции. IQueryable является абстракцией запроса базы данных, но функции, предоставляемые IQueryable, зависят от поставщика. Различный провайдер = другой набор функций.

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