Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Interaction between unit of work and repository patterns

After reading thorugh plenty of articles I am still unsure about the responsibilities of Unit of Work pattern when interacting with repositories.

Repositories are responsible for loading and saving Aggregate root entities, so consider the following example code:

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

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

The unit of work interface would be defined with the following methods:

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

Lets say the repository is implemented using a very straightforward SQL Mapper, so the FindByName contains some direct SQL to return ARoot, would the Save implementation look something like this:

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

The Unit Of Work Commit code would then construct all the required SQL to map the entity back into the DB?

Question 2)

If I add an aggregate root into the Unit of work, is the unit of work responsible for persisiting the root, and its child enitities, or should be the Save method of the repository add the changed entities into the Unit Of Work? e.g

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

OR... Alternativly

Does a Unit of work only deal with aggregate roots, and when commited calls the repository Save methods for each object in its change set, keeping the SQL mapping code to persist the entity in the Repository, changing the first code example to

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();
}

Thanks,

James

like image 293
James Simpson Avatar asked Jan 21 '10 22:01

James Simpson


People also ask

What is relationship between Repository and unit of work?

Unit of Work is the concept related to the effective implementation of the repository pattern. non-generic repository pattern, generic repository pattern. Unit of Work is referred to as a single transaction that involves multiple operations of insert/update/delete and so on.

How does repository pattern work?

The idea behind the Repository pattern is to decouple the data access layer from the business access layer of the application so that the operations (such as adding, updating, deleting, and selecting items from the collection) is done through straightforward methods without dealing with database concerns such as ...

What is the use of unit of work pattern?

The repository and unit of work patterns are intended to create an abstraction layer between the data access layer and the business logic layer of an application.


1 Answers

In our project we use a Repository to behave just like a collection of Entities, and the UnitOfWork is used to track the changes on those entities, and for writing them back to the data store.

If you're using LinqToSql or some other OR Mapper, then that is likely to implement a UnitOfWork pattern in itself, so often we just the ORMapper instance in our own IUnitOfWork.

Our repository interface is usually something like..

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

We don't have any save method in the Repository. If we don't need a UnitOfWork, then the Add/Remove methods are acting directly on the datastore.

If we need a UnitOfWork, then the public interface is something like...

void Commit();
void Rollback();

The repository has an internal interface with the UnitOfWork, so when we query the repository, the returned objects are tracked by the UnitOfWork for changes. The commit method writes the changes back to the datastore, the rollback method simply clears it's changes.

When we use LinqToSql the DataContext takes care of the change tracking, on Rollback we just instantiate a new Context. Persistence is handled, across the root and its children. One UnitOfWork instance is shared between all the Repositories.

When we don't use LinqToSql, then we implement our own UnitOfWork, maybe it calls a webservice or something, in this case we do change tracking in the entity classes themselves using an EntityBase class.

We have a repository for each root, but sometimes the children of one root are used as roots themselves, so we often need something like an OrderLineRepository, because we have a Use Case in our system were the user wants to search for Order lines.

like image 195
Andronicus Avatar answered Sep 18 '22 16:09

Andronicus