Я считаю, что если у вас есть ваши репозитории, используйте ORM, который уже достаточно абстрагирован от базы данных.
Однако там, где я сейчас работаю, кто-то считает, что у нас должен быть слой, который абстрагирует ORM на случай, если мы захотим изменить ORM позже.
Это действительно необходимо, или это просто слишком много, чтобы создать слой, который будет работать на многих ORM?
редактировать
Просто чтобы дать более подробную информацию:
- У нас есть класс POCO и класс сущностей, которые отображаются с помощью AutoMapper. Класс сущности используется слоем Repository. Затем уровень хранилища использует дополнительный уровень абстракции для взаимодействия с Entity Framework.
- Бизнес-уровень никоим образом не имеет прямого доступа к Entity Framework. Даже без дополнительного уровня абстракции над ORM необходимо использовать уровень обслуживания, который использует уровень хранилища. В обоих случаях бизнес-уровень полностью отделен от ORM.
- Основным аргументом является возможность изменить ORM в будущем. Поскольку он действительно локализован внутри слоя Repository, для меня он уже хорошо отделен, и я не понимаю, почему для создания «качественного» кода требуется дополнительный уровень абстракции.
Ответы:
Так лежит безумие. Крайне маловероятно, что вам когда-либо потребуется изменить ORM. И если вы когда-нибудь решите изменить ORM, затраты на переписывание сопоставлений составят ничтожную долю затрат на разработку и поддержку вашей собственной мета-ORM. Я ожидаю, что вы могли бы написать несколько сценариев для выполнения 95% работы, необходимой для переключения ORM.
Внутренние структуры - почти всегда катастрофа. Строительство одного в ожидании будущих потребностей - почти гарантированная катастрофа. Успешные структуры извлекаются из успешных проектов, а не создаются заранее для удовлетворения воображаемых потребностей.
источник
ORM предоставляет абстракцию для вашего уровня данных, чтобы он не зависел от своей РСУБД, но этого может быть недостаточно, чтобы «отвязать» ваш бизнес-уровень от уровня данных. В частности, вы не должны позволять объектам, которые сопоставляются с таблицами RDBMS, «просачиваться» непосредственно в бизнес-уровень.
По крайней мере, вашему бизнес-уровню необходимо программировать для интерфейсов, которые потенциально могут реализовать управляемые ORM объекты с отображением таблиц из уровня данных. Кроме того, вам может потребоваться создать интерфейсный слой построения абстрактных запросов, чтобы скрыть собственные возможности запросов в ORM. Основная цель состоит в том, чтобы избежать «внедрения» какого-либо конкретного ORM в ваше решение за пределами его уровня данных. Например, может возникнуть соблазн создать строки HQL ( Hibernate Query Language ) на бизнес-уровне. Однако это, казалось бы, невинное решение связало бы ваш бизнес-уровень с Hibernate, что позволило бы объединить бизнес и уровни доступа к данным; Вы должны стараться избегать этой ситуации в максимально возможной степени.
РЕДАКТИРОВАТЬ: В вашем случае дополнительный слой внутри хранилища является пустой тратой времени: исходя из вашей второй точки, ваш бизнес-уровень достаточно изолирован от вашего хранилища. Обеспечение дополнительной изоляции внесло бы ненужную сложность, без дополнительных преимуществ.
Проблема с созданием дополнительного уровня абстракции в вашем репозитории заключается в том, что конкретный «бренд» ORM определяет, как вы взаимодействуете с ним. Если вы создаете тонкую оболочку, которая выглядит как ваш ORM, но находится под вашим контролем, заменить базовый ORM будет примерно так же сложно, как и без этого дополнительного слоя. Если, с другой стороны, вы создаете слой, который не похож на ваш ORM, вам следует усомниться в выборе технологии объектно-реляционного отображения.
источник
UnitOfWork обычно предоставляет эту абстракцию. Это одно место, которое нужно изменить, ваши репозитории зависят от него через интерфейс. Если вам когда-нибудь понадобится изменить O / RM, просто внедрите новый UoW поверх него. Один и готово.
Кстати, это выходит за рамки простого переключения O / RM, подумайте о модульном тестировании. У меня есть три реализации UnitOfWork, одна для EF, одна для NH (потому что на самом деле мне пришлось переключить промежуточный проект O / RM для клиента, которому нужна поддержка Oracle), и одна для персистентности InMemory. Постоянство InMemory идеально подходило для модульного тестирования или даже для быстрого создания прототипов, прежде чем я был готов поставить за собой базу данных.
Фреймворк прост в реализации. Сначала у вас есть общий интерфейс IRepository
И интерфейс IUnitOfWork
Далее идет базовый репозиторий (ваш выбор - должен ли он быть абстрактным
Реализация IUnitOfWork - это детская игра для EF, NH и In Memory. Причина, по которой я возвращаю IQueryable, заключается в том, что по той же причине, как сказал Айенде в своем посте, клиент может дополнительно фильтровать, сортировать, группировать и даже проецировать результат, используя LINQ, и вы все равно получаете преимущество от того, что все это выполняется на стороне сервера.
источник