在 MVC 验证期间,简单注入器“操作无法完成,因为 DbContext 已被释放”

Simple Injector “The operation cannot be completed because the DbContext has been disposed” during MVC validation

我有一个很复杂的问题。我在 ASP.NET MVC 5 项目中使用 FluentValidation.MVC。在其中,我使用存储库模式来检查用户的电子邮件地址是否不重复。问题不在于存储库模式;这是存储库使用 Entity Framework 上下文在 运行 时间注入构造函数:

public class SomeRepository
{
  //IEFContext is something I modified the T4 template to generate
  public SomeRepository(IEFContext context)
  {
    _context = context;
  }
}

该应用程序使用了这种方法并且效果很好。 SimpleInjector 连接我的 EF 上下文,它的范围是使用 Per ASP.NET 网络请求(环绕 HttpContext.Items)。

Dim httpLifecycle = New SimpleInjector.Integration.Web.WebRequestLifestyle(True)
container.Register(of IEFContext, EFContext)(httpLifecycle)

此处的应用程序没有问题,只是验证问题。当服务器收到 post 操作时,我得到的错误是 "The operation cannot be completed because the DbContext has been disposed"。看来我不能在 FluentValidation 属性中使用任何与 EF 相关的代码,该属性在每个 Web 请求的基础上使用 EF 上下文。 validation 属性没有什么特别之处,它可以:

public class Val : AbstractValidator<Entity>
{
   public Val()
   {
       _repos = Container.GetInstance<ISomeRepos>();
       RuleFor(i => i.Email).Must((o, v) =>
       {
           _repos.HasDistinctEmail(o.ID, v);
       }
   }
}

自从存储在 HttpContext.Items 中以来,上下文应该随着先前的请求而消失。知道发生了什么事吗?我知道通过将 True 设置为 WebRequestLifecycle,我导致 EF 上下文在请求结束时被释放。我认为这是可取的。

我最好的选择是 Val class 的一个实例在 AppDomain 的持续时间内被缓存(一个单例),这意味着它的构造函数只被调用一次,因此它只解析了一个 ISomeRepos,导致该 repo 也被提升为单例(以及它的所有依赖项)。

快速修复很简单,将 GetInstance 调用移到委托中:

public Val()
{
    RuleFor(i => i.Email).Must((o, v) =>
    {
        repos = Container.GetInstance<ISomeRepos>();
        repos.HasDistinctEmail(o.ID, v);
    }
}