Entity Framework + Repository + Unit of Work
Introduction
The topic of this post is presentation an implementation of two quite popular data access patterns – Repository and Unit of Work – in Entity Framework.
Problem definition
Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
Unit of Work maintains a list of objects affected by a business transaction and coordinates the writing out of changes and the resolution of concurrency problems. Since EF contains several features of the UoW “out of the box” in this context we use UoW pattern when we need some additional behaviours ( mostly connected with concurrency checking) not provided by EF.
Solution
Firstly let’s define the interface representing Unit of Work pattern:
interface IUnitOfWork
{
void Commit();
void Rollback();
}
Next is an concrete class implementing this interface. We can notice that main work is done by ObjectContext class.
class UnitOfWork : IUnitOfWork, IDisposable
{
private readonly ObjectContext _context;
public UnitOfWork(ObjectContext context)
{
_context = context;
}
public void Commit()
{
//Some additional operations
// ...
_context.SaveChanges();
}
public void Rollback()
{
//Some additional operations
// ...
_context.Refresh(RefreshMode.StoreWins, object);
}
public void Dispose()
{
_context.Dispose();
}
}
When Unit of Work is created we can start implementing Repository pattern. As in previous example we start with an interface for this pattern.
interface IRepository<T> where T : class
{
IEnumerable<T> GetAll();
IEnumerable<T> GetByQuery(Expression<Func<T, bool>> where);
void Delete(T entity);
void Add(T entity);
}
Than the abstract repository class is created. While in UoW implementation main part of job is done by ObjectContex class, here the ObjectSet<T> is most useful.
abstract class AbstractRepository<T> : IRepository<T> where T : class
{
private readonly IObjectSet<T> _objects;
public AbstractRepository(ObjectContext context)
{
_objects = context.CreateObjectSet<T>();
}
public IEnumerable<T> GetAll()
{
return _objects.ToList();
}
public IEnumerable<T> GetByQuery(Expression<Func<T, bool>> where)
{
return _objects.Where(where);
}
abstract public T GetByID(int ID);
public void Delete(T entity)
{
_objects.DeleteObject(entity);
}
public void Add(T entity)
{
_objects.AddObject(entity);
}
}
The last step is creating a repository class for each our entity class. Below I present an example of such concrete repository.
class BookRepository : AbstractRepository<Books>
{
public BookRepository(ObjectContext context)
: base(context)
{
}
public override Books GetByID(int ID)
{
return _objects.First(n => n.ID == ID);
}
}
Eaxmple code
using (PracaEntities context = new PracaEntities())
{
IUnitOfWork unitOfWork = new UnitOfWork(context);
BookRepository bookRepo = new BookRepository(context);
bookRepo.Add(new Books());
unitOfWork.Commit();
}
Conclusion
This post presents usage of two very popular patterns – Repository and Unit of Work – in Entity Framework. Presented implementation gives us a possibility of encapsulation ObjectContext class in UnitOfWork class. We also have possibility of developing this class with more features and behaviours such as concurrency checking during save operations. The second part of post presented the implementation of repository pattern. The presented solution is generic and very easy for future development. Repository pattern provides developers a easy data access façade for each object set and defines most popular operations done on data sets.
Posted on 8 August 2011, in .NET Developing, Design Patterns, General and tagged C#, data access, data mapping, Design Patterns, repository, unit of work. Bookmark the permalink. Leave a Comment.
Leave a Comment
Comments (0)