SeanG80 SeanG80 - 1 month ago 5
C# Question

How to ensure that Autofac is calling Dispose() on EF6 DbContext

UPDATE

Found this little gem which helped me with DbContext
Josh Kodroff - Making Entity Framework More Unit-Testable

Original

After doing a lot of research I finally decided to implement IOC using Autofac in my MVC5 EF6 project. Autofac's documentation has been helpful, but I'm still not sure about whether or not I need to call Dispose() either in my Controller or Service Class?

I'm not using an abstracted UOW and Generic Repository, but just relying on DbContext and DbSet<> provided in EF6. Here's a snippet of my classes.

My DbContext

public class ProductContext : DbContext
{
public ProductContext() : base("ProductContext")
{
}

public DbSet<Availability> Availability { get; set; }
public DbSet<Category> Categories { get; set; }
....
}


My Service Class

public class ProductService : IProductService
{
private ProductContext _db;
public ProductService(ProductContext db)
{
_db = db;
}

public List<Product> GetProductsByCategory(string cleanCategory)
{
return _db.Products
.Include(p => p.Options.Select(o => o.OptionGroup))
.Include(p => p.Associations.Select(a => a.AssociatedGroup))
.Include(p => p.Variations).Include(p => p.Manufacturer)
.Where(p => p.Active && p.Category.Name.ToUpper().Equals(cleanCategory)).ToList();
}
.....
}


My Service Interface

public interface IProductService
{
List<Product> GetProductsByCategory(string cleanCategory);
....
}


My Contoller

public class ProductsController : Controller
{
private IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}

//GET: Products/
public ActionResult Index(string category)
{
if (String.IsNullOrEmpty(category))
{
return HttpNotFound();
}

string cleanCategory = urlScrubber(category);
var viewModel = new ProductsVM();
viewModel.ProductList = _productService.GetProductsByCategory(cleanCategory);
}


My Autofac Container

var builder = new ContainerBuilder();

// Register your MVC controllers.
builder.RegisterControllers(typeof(MvcApplication).Assembly);

// REGISTER COMPONENTS HERE:
builder.RegisterType<ProductContext>().AsSelf().InstancePerRequest();
builder.RegisterType<ProductService>().As<IProductService>().InstancePerRequest();

// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));


I have removed Dispose() from the controller with the understanding that Autofac would handle the disposal of contexts that inherit from IDisposable. Since ProductContext inherits from DbContext which includes a Dispose() Method, this should work.

Do I need to include something like

builder.RegisterType<ProductContext>().As<DbContext>().InstancePerRequest();


or will my current container work as expected calling Dispose?

builder.RegisterType<ProductContext>().AsSelf().InstancePerRequest();


Thanks for any help, I'm having a hard time locating documentation using Autofac without a generic repository and UOW on top of DbContext similar to my current pattern.

Answer

As per the doucmentation,

Autofac integration libraries standard unit-of-work lifetime scopes will be created and disposed for you automatically. Autofac’s ASP.NET MVC integration, a lifetime scope will be created for you at the beginning of a web request and all components will generally be resolved from there. At the end of the web request, the scope will automatically be disposed - no additional scope creation is required on your part.

So I think if your class implments IDisposable then Dispose() would be automatically called for such objects. So simply,

builder.RegisterType<ProductContext>().As<DbContext>().InstancePerRequest();

Would do the Disposal via object life scope management.