如何确保Autofac在EF6 DbContext上调用Dispose()

时间:2015-10-14 19:39:26

标签: c# entity-framework-6 autofac dispose

更新

找到了这个帮助我使用DbContext的小宝石 Josh Kodroff - Making Entity Framework More Unit-Testable

原始

经过大量研究后,我终于决定在我的MVC5 EF6项目中使用Autofac实现IOC。 Autofac的文档很有帮助,但我还不确定是否需要在Controller或Service Class中调用Dispose()?

我没有使用抽象的UOW和Generic Repository,只是依赖于DbContext和DbSet<>在EF6中提供。这是我课程的片段。

我的DbContext

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

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

我的服务类

    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();
    }
    .....
}

我的服务界面

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

我的控制器

    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);
}

我的Autofac容器

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));

我已从控制器中删除了Dispose(),并了解Autofac将处理从IDisposable继承的上下文的处理。由于ProductContext继承自包含Dispose()方法的DbContext,因此这应该有效。

我是否需要包含类似

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

或我当前的容器是否按预期调用Dispose?

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

感谢您的帮助,我很难在没有通用存储库的情况下使用Autofac查找文档,而在DbContext上使用类似于我当前模式的UOW。

2 个答案:

答案 0 :(得分:4)

根据doucmentation,

  

将自动为您创建和处置Autofac MySQL documentation标准工作单元生命周期范围。 Autofac的integration libraries,将在Web请求开始时为您创建生命周期范围,并且通常会从那里解析所有组件。在Web请求结束时,范围将自动处理 - 您无需创建额外的范围。

所以我认为如果你的班级为J <= J,那么IDisposable会自动调用这些对象。简单地说,

Dispose()

将通过对象生命范围管理进行处置。

答案 1 :(得分:2)

Autofac还支持在构造函数注入中使用Func<>。例如,您可以像平常一样注册数据上下文:

builder.RegisterType<ProductContext>().As<IProductContext>();

并在ProductService

中按如下方式使用
public class ProductService : IProductService
{
    private IProductContext _dbCreator;
    public ProductService(Func<IProductContext> dbCreator)
    {
        _db = db;
    }

    public List<Product> GetProductsByCategory(string cleanCategory)
    {
        using (var dbCtx = _dbCreator())
        {

            return dbCtx.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();
        }
    }
    .....
}

基本上,您的ProductService现在可以访问Func<>_dbCreator),每次调用时,都会根据您的autofac注册创建ProductContext的新实例,允许您在认为合适时处置实例。

我在写完之后意识到你没有IProductContext,我通常建议使用这种模式,但就你的问题而言,它并不太重要。您可以继续使用ProductContext的当前注册方法,然后传入Func<ProductContext>而不是IProductContext,即

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

private ProductContext _dbCreator;
public ProductService(Func<ProductContext> dbCreator)

很抱歉,如果代码没有编译,我没有使用IDE ...希望它足够让你明白我的观点!