Зачем мне использовать шаблон Unit of Work поверх сеанса NHibernate?

StackOverflow https://stackoverflow.com/questions/980584

  •  13-09-2019
  •  | 
  •  

Вопрос

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

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

Другие советы

Мой базовый рабочий интерфейс содержит следующие методы - Инициализировать - Зафиксировать - Откат - IDisposable.Утилизировать

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

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

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());
   }
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top