简体   繁体   中英

Is this a good UnitOfWork with Repository pattern Design around DDD

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..

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/

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM