3
\$\begingroup\$

I am building a web app with using UOW and Repository pattern. I have seen many different samples and found each one to be different, so not sure which is the correct way to go. I have a basic understanding of both these patterns 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:

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?

\$\endgroup\$
1
\$\begingroup\$

The UoW pattern has a couple of properties. The UoW will:

  • track changes to entities, wether that be adding, removing or updating.
  • coordinate the persisting of these changes in one atomic action. Which also means rolling back if an error occurs.

Since you're using EF, you don't have to implement this stuff, it's done for you. The ObjectContext is actually the UoW object. So unless you plan to switch out Persistence frameworks later on, any additional abstraction will be wasted effort.

I'm guessing you want to make sure your domain isn't aware of how it's persisted. Your domain should only know of the repository interfaces. The repository interfaces are actually part of your domain. The repository implementation though, is part of the persistance layer.

The repository implementation looks OK. I'm only curious about FindByFilter; if you're returning an IQueryable<T> object, you're saying you can query it. OTOH the FindByFilter function already takes an Expression<Func<T, bool>> filter parameter. I'd pick one of the two like the following:

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

or

public IQueryable<T> FindAll()
{
    //
}

Hope this helps.

\$\endgroup\$
  • \$\begingroup\$ Thanks for pointing out FindByFilter. I dont think it should return a queryable object. Will change that to a list. \$\endgroup\$ – user20358 Feb 21 '12 at 16:54
  • \$\begingroup\$ With respect to the UOW pattern, I guess I was trying to stretch the UOW concept a bit too much without fully understanding what it was for. My intent was to group a bunch of repositories by business case.. I dont want junior developers querying the wrong repositories for a particular application area. For eg. TableA can have child records in TableB for a particular area of the application and maybe TableC for another area of the application. I can now move the IUnitOfWork and its implementation to the Business layer. What do you think of that idea? \$\endgroup\$ – user20358 Feb 21 '12 at 17:00
  • \$\begingroup\$ Is the UOW pattern redundant with EF? There are lots of articles like this one on MSDN that use EF and UOW together. blogs.msdn.com/b/adonet/archive/2009/06/16/… \$\endgroup\$ – user20358 Feb 21 '12 at 17:07
  • \$\begingroup\$ The UoW pattern itself isn't redundant. It is already implemented by EF by the ObjectContext. In the article you mentioned the author created a custom IUnitOfWork interface to "make things more explicit", the comments on that article discuss the need for such an interface, since it doesn't really add any value on top of the ObjectContext. It's actually an implementation detail of how the repositories work. You might want to take a look at the onion architecture jeffreypalermo.com/blog/the-onion-architecture-part-3 \$\endgroup\$ – dvdvorle Feb 21 '12 at 18:54
  • 1
    \$\begingroup\$ That is a valid (infrastructure) concern, not a domain concern though. Luckily Entity Framework 4 has a solution for this, called Lazy Loading. In short this means that instead of querying the EntityB and EntityC data when EntityA is pulled out of the ObjectContext, the framework will make sure this data is only queried the moment your code actually accesses the EntityB and EntityC lists. It does have its own caveats, but there's a whole lot more information available. I'd suggest you start at msdn.microsoft.com/en-us/library/bb896272.aspx and work your way from there. \$\endgroup\$ – dvdvorle Feb 22 '12 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.