Взаимодействие между единицей работы и шаблонами хранилища - PullRequest
19 голосов
/ 22 января 2010

После прочтения большого количества статей я все еще не уверен относительно обязанностей шаблона «Единица работы» при взаимодействии с хранилищами.

Репозитории отвечают за загрузку и сохранение агрегированных корневых объектов, поэтому рассмотрим следующий пример кода:

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     roots.Save(root);
     uow.Commit();
}

Интерфейс единицы работы будет определяться следующими методами:

public interface IUnitOfWork
{
     void Insert(object);
     void Update(object);        
     void Delete(object);
     void Commit();
     void Rollback();
}

Допустим, репозиторий реализован с использованием очень простого SQL Mapper, поэтому FindByName содержит некоторый прямой SQL для возврата ARoot, будет ли реализация Save выглядеть примерно так:

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
}

Код коммита Unit Of Work затем сконструировал бы весь необходимый SQL для отображения сущности обратно в БД?

Вопрос 2)

Если я добавляю агрегатный корень в Единицу работы, отвечает ли единица работы за сохранение корня и его дочерних объектов, или должен ли метод Save хранилища добавить измененные сущности в Единицу работы? * например 1016 *

public void Save(T entity)
{
      IUnitOfWork uow = GetUnitOfWork();
      // Tell the UOW we are updating this entity
      uow.Update(entity);
      uow.Update(entity.AChildObject);
}

ИЛИ ... Альтернативно

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

using(IUnitOfWork uow = container.CreateUnitOfWork())
{
     Repository<ARoot> roots = container.GetRepository<ARoot>();
     ARoot root = root.FindByName("ARoot");
     root.Name = "ANewName";

     //roots.Save(root);
     uow.Update(root);
     // and commit
     uow.Commit();
}

Спасибо

Джеймс

Ответы [ 3 ]

3 голосов
/ 26 июня 2011

Обычно мне нравится видеть, как это делается, UoW отслеживает изменения, которые сохраняются, напрямую вызывая IRepository.Save ().

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

Передача единицы работы - это то, что приводит к тому, что изменения, сделанные путем вызова .Save () и других методов изменения, сохраняются. Вполне возможно, что UoW как-то отслеживает эти изменения.

3 голосов
/ 01 февраля 2010

В нашем проекте мы используем репозиторий, который ведет себя как набор сущностей, а UnitOfWork используется для отслеживания изменений в этих сущностях и для записи их обратно в хранилище данных.

Если вы используете LinqToSql или какой-либо другой OR Mapper, то, скорее всего, он реализует сам шаблон UnitOfWork, поэтому часто мы просто используем экземпляр ORMapper в нашем собственном IUnitOfWork.

Интерфейс нашего репозитория обычно похож на ..

  IEnumerable<Order> FindByCustomerId(string customerId);
  void Add(Order order);
  void Remove(Order order);

У нас нет метода сохранения в репозитории. Если нам не нужен UnitOfWork, то методы Add / Remove действуют непосредственно в хранилище данных.

Если нам нужен UnitOfWork, тогда общедоступный интерфейс - это что-то вроде ...

void Commit();
void Rollback();

Репозиторий имеет внутренний интерфейс с UnitOfWork, поэтому, когда мы запрашиваем репозиторий, возвращаемые объекты отслеживаются UnitOfWork на предмет изменений. Метод commit записывает изменения обратно в хранилище данных, а метод отката просто очищает их изменения.

Когда мы используем LinqToSql, DataContext заботится об отслеживании изменений, при откате мы просто создаем новый контекст. Настойчивость обрабатывается через корень и его детей. Один экземпляр UnitOfWork является общим для всех репозиториев.

Когда мы не используем LinqToSql, тогда мы реализуем наш собственный UnitOfWork, может быть, он вызывает веб-сервис или что-то еще, в этом случае мы отслеживаем изменения в самих классах сущностей, используя класс EntityBase.

У нас есть репозиторий для каждого корня, но иногда дочерние элементы одного корня сами используются в качестве корней, поэтому нам часто нужно что-то вроде OrderLineRepository, потому что в нашей системе есть вариант использования, в котором пользователь хочет найти Order линии.

2 голосов
/ 29 июня 2011
  • UnitOfWork - это ваша транзакция обработчик
  • Хранилище делает Актуальная работа по загрузке / сохранению объектов в хранилище данных

Я использую определения, подобные:

IUnitOfWork { Commit(); }
IRepository { GetAll(); GetById(); Add(T item); Remove(T item); }

У меня не будет UnitOfWork, создающего SQL - эта логика будет в вашем хранилище Какое хранилище данных вы используете?

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