【问题标题】:DbContext Disposed after first request when using Ninject's InRequestScope()使用 Ninject 的 InRequestScope() 时在第一次请求后处理 DbContext
【发布时间】:2012-06-24 09:00:08
【问题描述】:

我是 EF 和 Ninject 的新手,如果这没有意义,请原谅我 :)

我有一个包含 Ninject 和 Ninject.Web.Common 引用的 MVC3 应用程序。我正在尝试将 DbContext 注入我的存储库。我看到的是,在第一次请求时,一切都运行良好,但随后的请求返回:

System.InvalidOperationException: The operation cannot be completed because the DbContext has been disposed.
   at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)

我的绑定:

kernel.Bind<ISiteDataContext>().To<SiteDataContext>().InRequestScope();
kernel.Bind<IProductRepository>().To<ProductRepository>();
kernel.Bind<IProductService>().To<ProductService>();

我的服务类:

public class ProductService : IProductService {
    [Inject]
    public IProductRepository repository {get; set;}

    ...
}

我的存储库类:

public class ProductRepository : IProductRepository {
    [Inject]
    public ISiteDataContext context {get; set;}

    ...
}

我的 SiteDataContext 类:

public class SiteDataContext  : DbContext, ISiteDataContext 
{
    static SiteDataContext()
    {
        Database.SetInitializer<SiteDataContext >(null);
    }

    public DbSet<Product> Products{ get; set; }


    protected override void Dispose(bool disposing)
    {
        base.Dispose(disposing);
    }
}

我的控制器:

public class ProductController {
    [Inject]
    public IProductService productService {get; set;}

    ...
}

如果我删除 .InRequestScope(),那么它可以正常工作 - 但这会导致实体框架出现问题,因为对象在数据上下文的多个单独实例中被修改。

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework ninject


    【解决方案1】:

    也将您的存储库设置为 InRequestScope。他们应该在每次请求后处理。

    此外,对于 MVC,您还应该使用构造函数注入将您的存储库注入到您的控制器实例中。

    【讨论】:

    • 构造函数注入和属性注入有什么好处吗?
    • 当然,它遵循组合根。出于多种原因,对这种模式使用属性是不合适的。在这里使用构造函数注入可以很好地工作,并且它可以让依赖项尽早知道,并且由于没有理由将其作为默认的可选依赖项,因此它是首选方法。请参阅manning.com/seemann 这是关于该主题的最好的书恕我直言。
    • 我正在使用 DependencyResolver.Current.GetService
    【解决方案2】:

    当然,在我发布了一些点击后不久,我就解决了这个问题。

    问题在于,ActionFilters 的行为在 MVC3 中发生了变化,并且我有一个过滤器注入了我的 ProductService。

    我认为过滤器处理了服务并且最终处理了 DbContext。

    就我而言,解决方案很简单。我创建了第二个 DbContext,专门用于我的过滤器。由于过滤器仅查询几个表以验证对特定资源的授权,因此我不需要 DbContext 在单个请求中提供的工作单元上下文。我创建了一个使用新 DbContext 的新服务。在这种情况下,配置 InTransientScope() 就足够了

    【讨论】:

      【解决方案3】:

      我反对将 DbContext 放在 RequestScope 中,因为根据 NInject 文档,RequestScope 依赖于 HttpContext。不能保证在您的请求结束时将其处理掉。

      我曾经尝试将 DbContext 放在各种对象范围内,但似乎总是得到不一致的结果。

      Ninject 内核维护对作用域对象的弱引用,并在对作用域对象的弱引用不再有效时自动处置与作用域对象关联的对象。由于 InRequestScope() 使用 HttpContext.Current 或 OperationContext.Current 作为作用域对象,因此在销毁 HttpContext.Current 或 OperationContext.Current 之前,创建的任何关联对象都不会被销毁。由于 IIS/ASP.NET 管理这些对象的生命周期,因此对象的处置与 IIS/.NET 决定销毁它们的时间相关联,这可能无法预测。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-11
        • 1970-01-01
        • 2012-05-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多