Reputation:
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
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
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