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