I am using ASP.Net MVC 4, EF and Unity for DI. Also uses UnitOfWork pattern. Trying to figure out the best way to implement this. I have the code like below. The problem I am having is the Dispose() in Business and Repository layer never get called now, only the Destructor in both get called, so the objects seem to be never disposed. Please answer the following
Do I really need the IDisposable implementation in Business and Repository layer (if Unity is already taking care of it)
What should I do to get the Dispose() called(should I add it to the Controller too and Dispose all other objects or use some specific LifeTime manager)
Whether I should use the Singleton Instance of each or dispose it in each request as it is in the web environment.
Global.asax.cs:
private static IUnityContainer _unityContainer;
protected void Application_Start()
{
_unityContainer = UnityBootstrapper.SetupUnity();
_unityContainer.RegisterType<IController, ProductController>("Product");
DependencyResolver.SetResolver(new Microsoft.Practices.Unity.Mvc.UnityDependencyResolver(_unityContainer));
}
UnityBootstrapper.cs:
public class UnityBootstrapper
{
public static IUnityContainer SetupUnity()
{
UnityContainer container = new UnityContainer();
container.RegisterType<IProductDbContext, ProductDbContext>()
.RegisterType<IUnitOfWork, UnitofWork>(new InjectionConstructor(new ResolvedParameter(typeof(IProductDbContext))))
.RegisterType<IProductRepository, ProductRepository>()
.RegisterType<IProductBusiness, ProductBusiness>();
}
}
ProductController.cs:
public class ProductController : ControllerBase
{
private readonly IProductBusiness _productBusiness;
public ProductController(IProductBusiness productBusiness)
{
_productBusiness = productBusiness;
}
//No Dispose for this
}
ProductBusiness.cs:
public class ProductBusiness : IProductBusiness, IDisposable
{
private readonly IUnitOfWork _unitOfWork;
private readonly IProductRepository _productRepository;
public ProductBusiness(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_productRepository = _unitOfWork.ProductRepository;
}
public override void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected override void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
if (_productRepository != null) _productRepository.Dispose();
if (_unitOfWork != null) _unitOfWork.Dispose();
}
_isDisposed = true;
}
}
~ProductBusiness()
{
Dispose(false);
}
}
ProductRepository.cs:
public class ProductRepository : IProductRepository, IDisposable
{
private readonly IProductDbContext _context;
public ProductRepository(IProductDbContext context)
{
if (context == null)
throw new ArgumentNullException("context");
_context = context;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_isDisposed)
{
if (disposing)
{
if (_context != null) _context.Dispose();
}
_isDisposed = true;
}
}
~ProductRepository()
{
Dispose(false);
}
}
You don't really need to dispose objects, unless you do something specific during disposing process. DI containers take care of object lifetime for you.
Sometimes UoW implementation involves saving the changes on disposal. Try avoiding this. But if this is unavoidable, you can implement factory for that:
public interface IUnitOfWorkFactory
{
IUnitOfWork Create();
}
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
public IUnitOfWork Create()
{
return new UnitOfWork();
}
}
public class UnitOfWork : IUnitOfWork, IDisposable
{
// other implementation
public void Dispose()
{
context.SaveChanges();
}
}
and then consumer will do something like this:
public MyController(IUnitOfWorkFactory workFactory)
{
this.workFactory = workFactory;
}
public ActionResult DoSomething()
{
using(var uow = workFactory.Create())
{
//do work
}
}
This DI book chapter talks about disposable objects.
While Unity will manage disposing of your registered types, you still have to call dispose on your IOC container so that it does it for them.
Do it from Application_End and it should be fine.
protected void Application_End()
{
_unityContainer .Dispose();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With