user1360113
user1360113

Reputation:

DI with UnitOfWork and Repository patterns

As a learning process, I tried to implement the UoW with repository patterns and I have the following setup:

public interface IUnitOfWork : IDisposable
{
  MyEntities Context { get; set; }

  string GetConnectionString()
  void Complete();
}

public abstract class RepositoryBase<TEntity> : IRepository<TEntity> where TEntity : class
{
  protected MyEntities context;

  protected DbSet<TEntity> dbSet;

  protected RepositoryBase(IUnitOfWork unitOfWork)
  {
     context = unitOfWork.Context;
     dbSet = context.Set<TEntity>();
  }
}

public class ItemRepository : RepositoryBase<Item>, IItemRepository
{
  public ItemRepository(IUnitOfWork unitOfWork)
     : base(unitOfWork)
  {
  }

  public Item GetById(int id)
  {
     // return a item
  }
 }

To actually use the ItemRespoitory, I am doing the following:

using (var unitOfWork = new UnitOfWork())
{
    var ItemRepository = new ItemRepository(unitOfWork);

    var item = ItemRepository.GetById(1);
}

which works fine, and now I want to do this using IoC/DI with simple injector:

var container = new Container();

container.Register<IUnitOfWork, UnitOfWork>();
container.Register<IItemRepository, ItemRepository>();

container.Verify();

DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

But now my question is, since I am injecting the ItemRepository to the constructor of a controller

public MyController(IItemRepository itemRepository)
{
   _itemRepository = itemRepository;
}

how should I dispose the unit of work when I am done with the repository? because I don't have to create a unitofwork and wrap it in a using statement anymore. Am I doing this correctly? What should the right way of applying DI with UoW and repo patterns in my case? Thanks.

Upvotes: 1

Views: 515

Answers (2)

qujck
qujck

Reputation: 14578

You need to register your data services as per request - for the example above it would be either Per Web Request or Per Web Api Request

Find and install SimpleInjector.Integration.Web on nuget, and change this:

 container.Register<IUnitOfWork, UnitOfWork>();
 container.Register<IItemRepository, ItemRepository>();

to this (assuming MVC):

 container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
 container.RegisterPerWebRequest<IItemRepository, ItemRepository>();

and you're done.

Upvotes: 2

Aage
Aage

Reputation: 6252

If you're using a Unit Of Work (UoW) in combination with Repositories, a better way would be to set up the UoW to hold the repositories as properties and not inject the Uow into each Repository.

Example:

Unit of Work (interface):

public interface IUnitOfWork
{
    void Commit();
    IRepository<Store> Stores { get; }
    IRepository<Product> Products { get; }
}

Repository (interface):

public interface IRepository<T> where T : class
{
    IQueryable<T> GetAll();
    T GetById(Guid id);
    void Add(T entity);
    void Update(T entity);
    void Delete(T entity);
    void Delete(Guid id);
}

Now in your controller you would have:

public class ProductsController: Controller
{

    protected IUnitOfWork Uow { get; set; }

    public ProductsController(IUnitOfWork uow)
    {
        if (uow == null)
            throw new ArgumentNullException("Unit of Work");

        Uow = uow;
    }


}

And then setting up your IoC like so:

public static void RegisterIoc(HttpConfiguration config)
{
     var container = new Container();

     container.Register<IUnitOfWork, UnitOfWork>();
     container.Register<IRepository<Store>, Repository<Store>>();
     container.Register<IRepository<Product>, Repository<Product>>();

}

Now when you would need a Product from your DbContext you can just access the single Uow injected in your controllers. Also notice the Commit method, which would mean nothing more than a _dbContext.SaveChanges() call in your implementation. This is what a Unit of Work is all about, making some update calls to your DbContext and going to the database once. So, you have a transaction like setup (meaning, if something goes wrong in code, nothing will get updated in the database).

Note that this isn't a fully working example, but it should give you an idea how to set things up. If you want a tutorial on how you could get this working you could check out John Papa's Single Page Application course on PluralSight (that's where this code is based on). But he has a pretty complex setup (although very flexible), which might be a little much to start out with.

Upvotes: 0

Related Questions