8

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

  1. Do I really need the IDisposable implementation in Business and Repository layer (if Unity is already taking care of it)

  2. 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)

  3. 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);
    }
}   
abatishchev
  • 98,240
  • 88
  • 296
  • 433
SRAMPI
  • 373
  • 8
  • 23
  • Thank you all for the prompt response – SRAMPI Feb 20 '14 at 18:32
  • SA, welcome to StackOverflow. By convention in this community you say "Thank you" by up-voting answers. And then marking the most useful answer as accepted answer. Please have a look through FAQ section about up-voting: http://stackoverflow.com/help/why-vote – trailmax Feb 20 '14 at 23:27

4 Answers4

3

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.

trailmax
  • 34,305
  • 22
  • 140
  • 234
1

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();
    }
shenku
  • 11,969
  • 12
  • 64
  • 118
1

I believe if you set the correct LifetimeManager then no, you do not need to implement IDisposable as unity will handle disposing of your objects. This explains the different types of lifetime manager http://msdn.microsoft.com/en-us/library/ff660872(v=pandp.20).aspx.

Personally I have not used singletons, but just let the objects be created and then disposed of within each request.

B-Lat
  • 1,685
  • 1
  • 18
  • 25
0

You don't really need IDisposable on those classes since the main point of IDisposable is to clean up unmanaged resources. Take a look at these:

http://msdn.microsoft.com/en-us/library/system.idisposable(v=vs.110).aspx

Proper use of the IDisposable interface

Using the singleton pattern for your container can be helpful if you're using your container in a service location fashion. However, there are other (and arguably better) ways to use Unity or other DI/IoC containers. There are a few bootstrappers out there. For example:

https://www.nuget.org/packages/Unity.Mvc/

Community
  • 1
  • 1
Chris Anderson
  • 666
  • 3
  • 4