1

I am building a web app with using UOW and Repository pattern. I have a basic understanding of the same and I wanted to know if I should keep one UOW implementation for all the tables in my project or keep a separate one as per functionality like for eg:

public interface IHomeUOW
{
    IGenericRepository<User> Users { get; }
    IGenericRepository<TableA> Table_A { get; }
    IGenericRepository<TableB> Table_B{ get; }
}

public interface IBusinessCaseUOW
{

    IGenericRepository<TableA> Table_A { get; }
    IGenericRepository<TableXYZ> Table_XYZ{ get; }
}

As you can see TableA is available in both Home UOW as well as a particular business case UOW. One UOW partially implemented as below:

public class UnitOfWork : IUnitOfWork
{

    private readonly ObjectContext _context;
    private UserRepository _userRepository;


    public UnitOfWork(ObjectContext Context)
    {

        if (Context == null)
        {
            throw new ArgumentNullException("Context wasn't supplied");
        }
        _context = Context;
    }

    public IGenericRepository<User> Users
    {
        get
        {
            if (_userRepository == null)
            {
                _userRepository = new UserRepository(_context);
            }

            return _userRepository;
        }
    }
 }

My repositories will be like so

    public interface IGenericRepository<T>
    where T : class
    {
        //Fetch records
        T GetSingleByRowIdentifier(int id);             
        T GetSingleByRowIdentifier(string id);          

        IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter);  

        // CRUD Ops
        void AddRow(T entity);
        void UpdateRow(T entity);
        void DeleteRow(T entity);

    }


    public abstract class GenericRepository<T> : IGenericRepository<T>
            where T : class
    {
        protected IObjectSet<T> _objectSet;
        protected ObjectContext _context;

        public GenericRepository(ObjectContext Context)
        {
            _objectSet = Context.CreateObjectSet<T>();
            _context = Context;
        }

        //Fetch Data
        public abstract T GetSingleByRowIdentifier(int id);
        public abstract T GetSingleByRowIdentifier(string id);


        public IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter)
        {
            //
        }

        //CRUD Operations implemented

    }

   public class UserRepository : GenericRepository<User>
   {
         public UserRepository(ObjectContext Context)
         : base(Context)
         {
         }

         public override User GetSingleByRowIdentifier(int id)
         {
          //implementation
         }

         public override User GetSingleByRowIdentifier(string username)
         {
          //implementation
         }
   }

What do you think? If this is not the correct implementation of UOW and Repository pattern for DDD, will it fail as just a bunch of code written to abstract the call to the EF tables?

Thanks for your time..

user20358
  • 14,182
  • 36
  • 114
  • 186
  • This could be a candidate post for the [new codereview stackexchange site](http://codereview.stackexchange.com/). This is _not_ a criticism of the OP, as they are not likely to have heard of it yet. – Kurt Johnson Feb 17 '12 at 14:49
  • Apparently, the OP [_has_](http://codereview.stackexchange.com/questions/9091/will-this-work-as-unitofwork-with-repository-pattern-design-around-ddd) heard of it. Duplicate post. – Kurt Johnson Feb 17 '12 at 14:50
  • Hi Kurt, actually I did see the other site after I made this post. now that it has answers I can't take it off. Also this site seems to be getting more hits as probably not many people know the other one, which would explain why there are lesser views and no answers there. – user20358 Feb 17 '12 at 15:32

2 Answers2

6

I'm allergic to generic repositories. Each time I've used one I've had to do workarounds which breaks open/closed principle.

I recommend that you switch to root aggregate specific repositories and use your OR/M in them.

As for unit of work. EF and nhibernate do already implement the pattern. Simply create an interface like:

public interface IUnitOfWork : IDisposable
{
    void SaveChanges();
}

Disposing without saving = Rollback.

A nhibernate implementation would look like (quick writeup, not tested):

public class NHibernateUnitOfWork : IDisposable
{
    public NHibernateUnitOfWork(ISession session)
    {
        _transaction = session.BeginTransaction();
    }

    public void SaveChanges()
    {
        _transaction.Commit();
    }

    public void Dispose()
    { 
        _transaction.Dispose();
    }
}

Using an IoC container makes it really easy. Just register the implementation in it.

My favorite solution to get transaction support in ASP.NET MVC is to create a custom ActionFilter named something like TransactionalAttribute and let it handle the UnitOfWork implementation:

[HttpPost, Transactional]
public ActionResult Update(YourModel model)
{
}

I just converted the answer into a more detailed blog post: http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/

jgauffin
  • 99,844
  • 45
  • 235
  • 372
  • Root aggregate: `Order`. Aggregate: `OrderLine` – jgauffin Feb 17 '12 at 13:39
  • ok. In my code if this is not the correct implementation of UOW and Repository pattern for DDD, will it fail as just a bunch of code written to abstract the call to the EF tables? Sorry if I am sounding a bit lame. This is the first time I am implementing both these patterns and also using MVC – user20358 Feb 17 '12 at 13:53
  • DDD is about solving specific problems. Generic repositories tries to solve a generic problem. So the two doesn't get along together imho. Use EF in your specific repositories to take full advantage of it's features. – jgauffin Feb 17 '12 at 14:19
  • Thanks. I am trying to get my head around this. So in your blog example, how would the MVC update action method invoke an update on the table using the UOW class?.. or will it use the Repository class? – user20358 Feb 17 '12 at 14:45
  • My example uses an inversion of control container which will handle the UoW. – jgauffin Feb 18 '12 at 11:31
  • @user20358: The unit of work is really just a transaction wrapper. The repository are used for the update, but the UoW are used to commit it do the db. – jgauffin Feb 21 '12 at 08:29
1

I think this is wrong.

UnitOfWork is Transaction (in simple words). It least it should contain one method Complete(Commit).

If you work with EntityFramework you wrap ObjectContext, if you work with pure ADO .NET you wrap TransactionScope, if with NHibernate ISession, etc.

Here is my UOF:

public interface IUnitOfWork : IDisposable
{
    void Complete();
    TRepository GetRepository<TRepository, TItem>()
        where TRepository : IRepository<TItem>
        where TItem : class;
}
Alex Burtsev
  • 12,418
  • 8
  • 60
  • 87
  • 1
    I do rollback in Dispose if Complete wasn't called (like TransactionScope does) – Alex Burtsev Feb 17 '12 at 13:13
  • I've added a partial implementation to my UOW.. My implementation is based off this article : http://www.codeproject.com/Articles/94782/Revisiting-the-Repository-and-Unit-of-Work-Pattern – user20358 Feb 17 '12 at 13:19
  • @user20358 the implementation in link you provided is not perfect but it's OK, if you don't need to support anything except EF. I would recommend using concrete Repositories, like MyProductRepository : IRepository – Alex Burtsev Feb 17 '12 at 13:24
  • I'm only supporting EF at the moment. So that means I dont bring in the UOW pattern? From my code I directly work with the concrete repository .. correct? – user20358 Feb 17 '12 at 13:29
  • @user20358, not quite. EF itself is realization of repository pattern, it's UOF is called ObjectContext, it's repository is called ObjectSet. If you don't plan to use anything except EF you do not need abstraction on top of it. But it is a good manner (and practice) to create one. – Alex Burtsev Feb 17 '12 at 13:33
  • There are so many different implementations of these two patterns in conjunction. I tried getting the commit method in the UOW implementation as described in the link, but then I wasn't able to delete and update records with the commit in the UOW.. when I moved it to the GenericRepository it did all the actions Add,Delete,Update properly and my UOW implmentation just became another abstraction over the Repository. Can you suggest some reading material that will help me understand these concepts correctly, specially how EF is a realization of the Repository pattern.. – user20358 Feb 17 '12 at 16:44
  • Thanks. My apologies for sounding lame :) – user20358 Feb 17 '12 at 16:45