0

I would like to implement simple IGenericRepository and IUnitOfWork interfaces in my application but I'm not sure whats the best way to do it.

As far as I could understand, UnitOfWork should be used for writing, while Repository should be used for reading. I have encountered one architecture and I really like it, but I only found interfaces and not the implementations, and I'm not sure how should I implement those.

public interface IGenericRepository : IDisposable
{
    IUnitOfWork CreateUnitOfWork();
    T FirstOrDefault<T>(Expression<Func<T, bool>> predicate) where T : class, IBaseEntity;
    IQueryable<T> Get<T>(Expression<Func<T, bool>> predicate = null, Func<IQueryable<T>, IOrderedQueryable<T>> sorter = null, params string[] includeProperties) where T : class, IBaseEntity;
    IQueryable<T> GetAll<T>() where T : class, IBaseEntity;
    IDbContext GetDbContext();
}

public interface IUnitOfWork : IDisposable
{
    int Commit();
    bool Delete<T>(T entity) where T : class, IBaseEntity;
    int DeleteItems<T>(IList<T> entities) where T : class, IBaseEntity;
    bool Insert<T>(T entity) where T : class, IBaseEntity;
    int InsertItems<T>(IList<T> entities) where T : class, IBaseEntity;
    bool Update<T>(T entity) where T : class, IBaseEntity;
    int UpdateItems<T>(IList<T> entities) where T : class, IBaseEntity;
}

I'm not sure how should those work. Should I use IDbContextFactory within repository to share DbContext between Repository and UnitOfWork or they should have separate DbContexts? If I implement UnitOfWork for write and Repository for read, should there be UnitOfWorks DbContext for write and Repositorys DbContext for read or they should share same DbContext?

I would really appreciate good explanation of how DbContext and UnitOfWork/Repository should work.

Those would be implemented in service in such way:

public CustomerService(IGenericRepository repository)
{
    this.repository = repository;
    this.context = this.repository.GetDbContext();
}

public void UpdateCustomer(Customer customer)
{
    var uow = this.repository.CreateUnitOfWork();
    uow.AddForSave(customer);
    uow.Commit();
}

public List<Customer> GetAll()
{
    return this.repository.GetAll<Customer>();
}

Any help, explanation about DbContext and UoW/Repository relation, or good tutorial similar to this implementation would help.

Regards.

zhuber
  • 5,364
  • 3
  • 30
  • 63
  • 1
    `UnitOfWork should be used for writing, while Repository should be used for reading` I've never heard of that – Jonesopolis Jul 16 '15 at 21:21
  • Not should as "must", but is advised for many entity update (single entity can be updated with repository). Although there are many great patterns to use repository for both but I would like to stick with this one. – zhuber Jul 16 '15 at 21:25
  • @Disappointed has a good link for you. But be aware that UoW and Repository patterns are very much debated, some would say deprecated. Certainly in an EF/MVC environment, where DbContext and DbSet already fulfill most of this functionality. – H H Jul 16 '15 at 21:40
  • 1
    The (main) purpose of the the UoW and Repository patterns are to decouple the data access implementation from the rest of your application. A very good point pro using these patterns with EF is presented here: http://stackoverflow.com/a/21361903/1942895 – Rafael Companhoni Jul 16 '15 at 21:46
  • It is a good link to read. But I notice that that answer is the minority view over there. – H H Jul 16 '15 at 21:49
  • Agree with @Henk Holterman, here are a couple of links related to the use of the repository pattern and the unit of work: http://rob.conery.io/2014/03/04/repositories-and-unitofwork-are-not-a-good-idea/ and http://www.thereformedprogrammer.net/is-the-repository-pattern-useful-with-entity-framework/ – Alan Macgowan Jul 16 '15 at 21:50
  • When it comes to system architecture there's no right or wrong but the right choices for the the current situation. – Rafael Companhoni Jul 16 '15 at 21:51
  • @rcompanhoni Correct, thats why I would like it implemented this way that I described, but can't make it working... – zhuber Jul 17 '15 at 12:53

1 Answers1

0

I would like to recommend that you avoid the Repository pattern, for inserts/updates.

You should consider "command/query objects" as an alternative, you can find a bunch of interesting articles around this area, but here is a good one:

https://rob.conery.io/2014/03/03/repositories-and-unitofwork-are-not-a-good-idea/

You would stick to a single command object per command to enable simple transactions, avoiding the need for the complexity of the Unit Of Work pattern.

However, if you are thinking a Query object per query is overkill, this would often be right. Instead you might choose to start with a 'FooQueries' object, which is essentially a Repository but only for Queries. 'Foo' might be your 'domain aggregate' in the DDD sense.

Later, you might find splitting out individual query objects worthwhile if you want to add cross cutting concerns via attributes, you could even feed a query object into a pipeline.

Darren
  • 9,014
  • 2
  • 39
  • 50