Как абстрагировать NHibernate, чтобы избежать узкой зависимости и облегчить тестирование - PullRequest
3 голосов
/ 10 марта 2010

Можно ли принять использование O / RM, такого как NHibernate или Entity Framework, и абстрагировать его таким образом, чтобы его можно было заменить в случае возникновения ситуации, которую O / RM не может обработать.

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

Я бы рассмотрел шаблон репозитория, чтобы операция службы запрашивала у репозитория сущности, а сеанс O / RM был встроен в репозиторий. Но что вы делаете с сохранением связанных сущностей, и метод Update (T entity) сбрасывает изменения немедленно. Это кажется простым и в целом неудовлетворительным.

То, к чему я сейчас склоняюсь, - это один класс-оболочка O / RM, который предоставляет интерфейс с общими методами, такими как «StartSession», «EndSession», «AbandonSession», «GetById (object id)» и т. Д.

По крайней мере, это позволило бы подделать OR / M при тестировании, что является еще одной моей большой проблемой.

Полагаю, я говорю, что не хочу тесно переплетать бизнес-логику и код доступа к данным O / RM, потому что переключение на другое O / RM может привести к замене большей части этого кода.

Что люди делают в реальном мире?

Ответы [ 3 ]

8 голосов
/ 19 марта 2010

Мое твердое мнение состояло бы в том, чтобы провести несколько тестов для небольших проектов и выбрать набор инструментов для использования заранее, а не откладывать решение на потом, создав абстрактную оболочку, которую вы сможете изменить «когда-нибудь». По моему опыту, когда-нибудь никогда не придет, и сложность, которую вы вводите, не стоит.

В прошлом я пытался создать универсальную оболочку для nHibernate и, по сути, из-за этого столкнулся только с болью. ORM Tools - это действительно обертка и набор инструментов. Когда вы пытаетесь создать оболочку оболочки, вам в конечном итоге необходимо разработать (и впоследствии поддерживать) относительно сложные инструменты и механизмы, чтобы выполнить то, что вы упаковываете, делает изначально.

И, по моему собственному опыту, оболочка, которую я потратил БОЛЬШОЕ количество времени на сборку, в итоге раскрыла лишь часть возможностей базовых инструментов ORM. И тогда я НИКОГДА не заканчивал тем, что использовал обертку с чем-то кроме nHibernate ... так что я мог бы сэкономить огромное количество времени и усилий, просто используя сам vanilla nHibernate.

Я бы рекомендовал внимательно изучить ваши требования и вместо того, чтобы тратить время на абстрагирование решения швейцарского армейского ножа, провести исследование, сначала выбрать набор инструментов и работать с ним. Да, ваш код будет тесно связан со сторонним инструментом, но код будет проще, вы получите его быстрее и, вероятно, результаты будут лучше.

Надеюсь, это поможет,

Макс Шиллинг

1 голос
/ 11 марта 2010

Я обрабатываю транзакции C / U / D в базе данных с шаблоном единицы работы. Я не захожу намного дальше, чем абстракция, потому что я не хочу абстрагировать абстракцию. Linq - хорошая абстракция для запрашивающей части, общий репозиторий - хорошая абстрактная часть для запрашивающей части. Вот абстракции, которые я использую практически в любом проекте с реляционной базой данных:

interface IRepository<T> : IQueryable<T>
{
   void Add(T entity);
   void Remove(T entity);
   T Get(Guid id);
}

interface IUnitOfWork : IDisposable
{
   void RollBack();
   void Commit();
}

// I don't do this every time, the generic repository is enough for almost everything.
[Example]
interface IOrderRepository : IRepository<Order>
{
   IList<Order> GetOrdersForUser(User user);
}

// This interface is only used in the repository implementation
interface INHiberanteUnitOfWork : IUnitOfWork
{
  ISession Session { get; }
}

Иногда я использую общий репозиторий, иногда я использую более конкретный общий репозиторий с поддержкой шаблонов спецификаций, а иногда я создаю отдельный репозиторий для определенного типа сущности. Вы можете найти переполнение стека в NHibernate + Единица работы, чтобы найти больше информации о реализации этих шаблонов.

Я не абстрагирую отображение, потому что каждая форма имеет свои особенности в отображении, и я думаю, что отображение уже является абстракцией. Я использую fluentnhibernate для отображения.

0 голосов
/ 11 марта 2010

Один из вариантов - определить модель вашего домена как POCO, а затем использовать BoostMap для прокси между вашими пользовательскими типами и базовым OR / M. Это позволяет вам при необходимости заменить основной OR / M, а также смоделировать исходный код iQueryable для модульного тестирования, которое не зависит от базы данных: -)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...