Зачем мне использовать шаблон единиц работы поверх сеанса NHibernate? - PullRequest
5 голосов
/ 11 июня 2009

Когда я напишу реализацию UoW поверх того, что уже предоставлено NHibernate? Какие-нибудь примеры из реального мира?

Ответы [ 3 ]

5 голосов
/ 11 июня 2009

Единица работы, которую вы описываете, уже предоставлена ​​NHibernate, поэтому нет никаких причин делать такую ​​единицу работы.

То, что мы имеем в нашей Службе WCF, - это единица работы более высокого уровня, которая содержит информацию, важную в нашем приложении для текущей единицы работы. Это включает в себя абстрагирование NHibernate ISession для нас. Когда вы разбиваете его, у вас есть код, который вписывается в три категории

  1. Код, который должен иметь дело с единицей работы. Неважно, кто поддерживает единицу работы. Это может быть NHibernate, iBatis или пользовательский ORM. Все, что нужно сделать, это загрузить, откатиться, сохранить и т. Д. Его не должно интересовать механизм, используемый для этого.

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

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

Хотя код в 1. может просто работать против ISession, мы предпочитаем абстрагироваться от кода, который мы не контролируем напрямую или который может измениться. Это имеет значение по двум причинам.

  • Когда мы начинали, мы не были на 100% проданы на NHibernate. Мы рассматривали iBatis или что-то на заказ. Очевидно, это больше не проблема.

  • Вся команда не является экспертом в NHibernate, и мы не хотим, чтобы они были. По большей части люди пишут код, который вписывается в категорию 1. Все, что они знают, это наша единица работы. Когда код в категории 2. должен быть написан, его пишут люди из команды, которые хорошо понимают NHibernate.

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

1 голос
/ 11 июня 2009

Моя базовая единица работы интерфейса содержит следующие методы - инициализировать - совершить - откат - IDisposable.Dispose

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

0 голосов
/ 11 июня 2009

При условии, что вы правильно настроили все сопоставления (то есть каскады), вам не нужно делать ничего особенного, и ISession будет работать нормально. Однако, если вы пишете 3-уровневое приложение, вам придется вручную упорядочивать операции базы данных, которые вы хотите выполнить в одной транзакции. Хорошей отправной точкой может служить «эталонная реализация» Фаулера в «Шаблонах архитектуры корпоративных приложений»:

class UnitOfWork... 

   public void registerNew(DomainObject obj) {
      Assert.notNull("id not null", obj.getId());
      Assert.isTrue("object not dirty", !dirtyObjects.contains(obj));
      Assert.isTrue("object not removed", !removedObjects.contains(obj));
      Assert.isTrue("object not already registered new", !newObjects.contains(obj));
      newObjects.add(obj);
   }
   public void registerDirty(DomainObject obj) {
      Assert.notNull("id not null", obj.getId());
      Assert.isTrue("object not removed", !removedObjects.contains(obj));
      if (!dirtyObjects.contains(obj) && !newObjects.contains(obj)) {
         dirtyObjects.add(obj);
      }
   }
   public void registerRemoved(DomainObject obj) {
      Assert.notNull("id not null", obj.getId());
      if (newObjects.remove(obj)) return;
      dirtyObjects.remove(obj);
      if (!removedObjects.contains(obj)) {
         removedObjects.add(obj);
      }
   }
   public void registerClean(DomainObject obj) {
      Assert.notNull("id not null", obj.getId());
   }
...