如何确保 Autofac 在 EF6 DbContext 上调用 Dispose()
How to ensure that Autofac is calling Dispose() on EF6 DbContext
更新
找到这个小 gem 帮助我使用 DbContext
Josh Kodroff - Making Entity Framework More Unit-Testable
原创
经过大量研究后,我最终决定在我的 MVC5 EF6 项目中使用 Autofac 实现 IOC。 Autofac 的文档很有帮助,但我仍然不确定是否需要在我的控制器或服务中调用 Dispose() Class?
我没有使用抽象的 UOW 和通用存储库,而是依赖于 EF6 中提供的 DbContext 和 DbSet<>。这是我的 类.
的片段
我的 DbContext
public class ProductContext : DbContext
{
public ProductContext() : base("ProductContext")
{
}
public DbSet<Availability> Availability { get; set; }
public DbSet<Category> Categories { get; set; }
....
}
我的服务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();
}
.....
}
我的服务界面
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 类似于我当前的模式。
根据文档,
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.
所以我认为如果您的 class 实现 IDisposable
那么 Dispose()
将自动为此类对象调用。如此简单,
builder.RegisterType<ProductContext>().As<DbContext>().InstancePerRequest();
将通过对象生命范围管理进行处置。
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...希望它足够接近你明白我的意思!
更新
找到这个小 gem 帮助我使用 DbContext Josh Kodroff - Making Entity Framework More Unit-Testable
原创
经过大量研究后,我最终决定在我的 MVC5 EF6 项目中使用 Autofac 实现 IOC。 Autofac 的文档很有帮助,但我仍然不确定是否需要在我的控制器或服务中调用 Dispose() Class?
我没有使用抽象的 UOW 和通用存储库,而是依赖于 EF6 中提供的 DbContext 和 DbSet<>。这是我的 类.
的片段我的 DbContext
public class ProductContext : DbContext
{
public ProductContext() : base("ProductContext")
{
}
public DbSet<Availability> Availability { get; set; }
public DbSet<Category> Categories { get; set; }
....
}
我的服务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();
}
.....
}
我的服务界面
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 类似于我当前的模式。
根据文档,
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.
所以我认为如果您的 class 实现 IDisposable
那么 Dispose()
将自动为此类对象调用。如此简单,
builder.RegisterType<ProductContext>().As<DbContext>().InstancePerRequest();
将通过对象生命范围管理进行处置。
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...希望它足够接近你明白我的意思!