Мне просто нужно было отключить ORM, и это было довольно сложной задачей, потому что логика запросов просачивалась повсюду. Если бы мне когда-либо приходилось разрабатывать новое приложение, я бы предпочел инкапсулировать всю логику запросов (используя ORM), чтобы защитить ее от изменений в будущем. Шаблон репозитория довольно сложен для кодирования и поддержки, поэтому мне было интересно, есть ли какие-либо другие шаблоны для решения проблемы?
Я могу предвидеть сообщения о том, чтобы не добавлять дополнительную сложность до того, как она действительно понадобится, быть гибкой и т. Д., Но меня интересуют только существующие шаблоны, решающие аналогичную проблему более простым способом.
Моей первой мыслью было создание репозитория универсальных типов, в который я добавлял методы по мере необходимости к классам репозиториев определенных типов с помощью методов расширения, но модульное тестирование статических методов ужасно болезненно. IE:
public static class PersonExtensions
{
public static IEnumerable<Person> GetRetiredPeople(this IRepository<Person> personRep)
{
// logic
}
}
источник
Ответы:
Прежде всего: универсальный репозиторий должен рассматриваться как базовый класс, а не как полная реализация. Это должно помочь вам получить общие методы CRUD. Но вы все равно должны реализовать методы запроса:
Во-вторых:
Не возвращайся
IQueryable
. Это дырявая абстракция. Попробуйте реализовать этот интерфейс самостоятельно или использовать его без ведома основного поставщика БД. Например, у каждого провайдера БД есть собственный API для активной загрузки сущностей. Вот почему это дырявая абстракция.альтернатива
В качестве альтернативы вы можете использовать запросы (например, как определено шаблоном разделения Command / Query). CQS описана в википедии.
Вы в основном создаете классы запросов, которые вы вызываете:
Самое замечательное в запросах заключается в том, что вы можете использовать разные методы доступа к данным для разных запросов, не загромождая код. например, вы можете использовать веб-сервис в одном, nhibernate в другом и ADO.NET в третьем.
Если вы заинтересованы в реализации .NET, прочитайте мою статью: http://blog.gauffin.org/2012/10/griffin-decoupled-the-queries/
источник
YourProject.YourDomainModelName.Queries
это будет легко ориентироваться.Сначала я думаю, что ORM - это уже достаточно большая абстракция над вашей базой данных. Некоторые ORM обеспечивают привязку ко всем распространенным реляционным базам данных (NHibernate имеет привязки к MSSQL, Oracle, MySQL, Postgress и т. Д.). Поэтому создание новой абстракции поверх этого не кажется мне выгодным. Кроме того, спорить о том, что вам нужно «абстрагироваться» от этого ORM, не имеет смысла.
Если вы все еще хотите построить эту абстракцию, я бы пошел против шаблона репозитория. Это было здорово в эпоху чистого SQL, но это довольно хлопотно для современного ORM. Главным образом потому, что вы в конечном итоге повторно внедрили большинство функций ORM, таких как операции CRUD и запросы.
Если бы я строил такие абстракции, я бы использовал эти правила / шаблоны
В конкретной реализации я бы использовал CRUD-операции ORM напрямую, без каких-либо переносов. Я бы также делал простые запросы прямо в коде. Но сложные запросы будут заключены в свои собственные объекты. Чтобы «спрятать» ORM, я бы попытался прозрачно внедрить контекст данных в объекты службы / пользовательского интерфейса и сделать то же самое для запросов к объектам.
Последнее, что я хотел бы сказать, это то, что многие люди используют ORM, не зная, как его использовать и как извлечь из него максимальную «прибыль». Люди, которые рекомендуют репозитории, обычно бывают такого рода.
В качестве рекомендуемого чтения я бы сказал блог Айенде , особенно эту статью .
источник
Проблема с утечкой реализации заключается в том, что вам нужно много разных условий фильтрации.
Вы можете сузить этот API, если вы реализуете метод репозитория FindByExample и используете его следующим образом
источник
Подумайте о том, чтобы заставить ваши расширения работать на IQueryable вместо IRepository.
Для модульного тестирования:
Для тестирования не требуется фальсификаций. Вы также можете комбинировать эти методы расширения для создания более сложных запросов по мере необходимости.
источник
IQueryable
плохая мама, точнее интерфейс БОГА. Его реализация очень полезна, и есть очень мало (если таковые имеются) полных поставщиков LINQ to Sql. б) Методы расширения делают расширение (один из основных принципов ООП) невозможным.Я написал довольно аккуратный шаблон объекта запроса для NHibernate здесь: https://github.com/shaynevanasperen/NHibernate.Sessions.Operations
Это работает с использованием интерфейса, подобного этому:
Учитывая класс сущности POCO как это:
Вы можете создавать объекты запроса следующим образом:
А затем используйте их так:
источник