1

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.

qujck
  • 14,388
  • 4
  • 45
  • 74
  • I think you could get around it by carefully controlling the lifetime of everything involved. Id say it'd have to be a per request lifetime, but from limited experience lifetimes are not always what they seem/purport to offer. – brumScouse Apr 26 '14 at 20:54

2 Answers2

2

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.

Steven
  • 166,672
  • 24
  • 332
  • 435
qujck
  • 14,388
  • 4
  • 45
  • 74
  • 1
    The reason this works out of the box is because the `RegisterPerWebRequest` extension methods make use of the `WebRequestLifestyle`. The `WebRequestLifestyle` inherits from the `ScopedLifestyle` base class which allows deterministic disposal of cached instances. In other words all scoped lifestyles (such as `LifetimeScopeLifestyle`, `WebApiRequestLifestyle` and `WebRequestLifestyle`) will ensure that created instances for that lifestyle will get disposed when the scope ends. – Steven Apr 28 '14 at 12:32
0

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.

Steven
  • 166,672
  • 24
  • 332
  • 435
Aage
  • 5,932
  • 2
  • 32
  • 57
  • 2
    The drawback of doing it this way is that it violates the [Open\Closed principle](http://en.wikipedia.org/wiki/Open/closed_principle) because you have to change the `UnitOfWork` each time you add a new data entity. See [here](http://stackoverflow.com/questions/16064902/dependency-injection-in-unit-of-work-pattern-using-repositories/16085891#16085891) for a working example of injecting the `UnitOfWork` into the `Repository`. – qujck Apr 27 '14 at 21:04
  • 1
    @qujck I never realised that. Thank you. – Aage Apr 30 '14 at 14:02