using UnitOfWork and Repository Pattern with Entity Framework

c# entity-framework repository-pattern unit-of-work

Question

I'm gonna to use repository and UnitOfwork in my data access layer to do this take a look at one contact aggregateroot

 public interface IAggregateRoot
    {
    }

this is my Generic repository interface :

 public interface IRepository<T>
        {
            IEnumerable<T> GetAll();
            T FindBy(params Object[] keyValues);
            void Add(T entity);
            void Update(T entity);
            void Delete(T entity);

        }

and my POCO Contact class in Model

 public class Contact :IAggregateRoot
        {
            public Guid Id { get; set; }
            public string Name { get; set; }
            public string Email { get; set; }
            public string Title { get; set; }
            public string Body { get; set; }
            public DateTime CreationTime { get; set; }
        }

and this my IContactRepository that inherit from IRepository and also maybe has it is own method

 public interface IContactRepository : IRepository<Contact>
        {
        }

Now I have done in IUitOfWork and UnitOfwork like this

public interface IUnitOfWork 
    {
        IRepository<Contact> ContactRepository { get; }
    }

public class UnitOfWork : IUnitOfWork
    {
        private readonly StatosContext _statosContext = new StatosContext();
        private IRepository<Contact> _contactUsRepository;

 public IRepository<Contact> ContactRepository
        {
            get { return _contactUsRepository ?? (_contactUsRepository = new Repository<Contact>(_statosContext)); }
        }
}

also about my Repository

public class Repository<T> : IRepository<T> where T : class, IAggregateRoot
    {
       //implementing methods 
    }

I can do all CRUD operation with accessing Repositories with UnitOfwork in Service , example :

_unitOfWork.ContactRepository.Add(contact);
            _unitOfWork.SaveChanges();

but I want to do like this

_

ContactRepository.Add(contact);
            _unitOfWork.SaveChanges();

(get CRUD and generic method via _ContactRepository No by _unitOfWork.ContactRepository) Because I want to get ContactRepository method to some specific queries , anybody help please ??

1
3
5/9/2013 5:26:52 PM

Accepted Answer

It's not a direct answer to your question, but it might simplify things a little bit and reduce duplication.

When you use e.g. EntityFramework Power Tools to reverse-engineer Code First (or just use Code First in general), you end up with the DbContext class that serves as a UoW and repository in one, e.g.:

public partial class YourDbContext : DbContext
{
    public DbSet<Contact> Contacts {get; set;}
}

Now, if you want things to be testable, there's an easy way: introduce a very thin interface:

public interface IDbContext
{
    IDbSet<T> EntitySet<T>() where T : class;
    int SaveChanges();
    //you can reveal more methods from the original DbContext, like `GetValidationErrors` method or whatever you really need.
}

then make another file with second part of the partial class:

public partial class YourDbContext : IDbContext
{
     public IDbSet<T> EntitySet<T>() where T : class
     {
         return Set<T>();
     }
}

Ta-da! Now you can inject IDbContext with YourDbContext backing it up:

//context is an injected IDbContext:
var contact = context.EntitySet<Contact>().Single(x => x.Id == 2);    
contact.Name = "Updated name";
context.EntitySet<Contact>().Add(new Contact { Name = "Brand new" });
context.SaveChanges();

Now if you want to have control over the disposal of the context, then you'd have to write your own (gasp) IDbContextFactory (generic or not, depending what you need) and inject that factory instead.

No need to write your own Find, Add or Update methods now, DbContext will handle that appropriately, it's easier to introduce explicit transactions and everything is nicely hidden behind interfaces (IDbContext, IDbSet).

By the way, the IDbContextFactory would be an equivalent to NHibernate's ISessionFactory and IDbContext - ISession. I wish EF had this out of the box, too.

11
6/27/2013 6:32:40 AM

Popular Answer

I agree with the Doctor, DbContext is already a UnitOfWork, and adding another UoW abstraction on top of it is typically redundant, unless you think it's highly likely you might switch database technologies in the future.

I don't agree, however, with treating DbSet's as repositories, since this tightly couples your queries to the methods that use them. If you need to change a query, you have to do it everywhere you use it.

I prefer to either use a stand-alone repository (or service interface, they serve similar functions) or to use more of a CQRS system for Command/Query Seperation, an use query objects.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow