SimpleInjector和System.Web.Mvc.Async线程

时间:2012-11-04 16:21:10

标签: dependency-injection inversion-of-control simple-injector

asked before a question在这里,我读了关于多线程的这个问题/答案,我知道这些解决方案。但今天我遇到了一个新问题。当我们使用命令(或者我们可以访问原始代码来管理和修改它)时,上述答案中建议的async-decorator可以正常工作。但是当MVC自己创建一个新线程时,我们能做什么?例如我有一个自定义角色提供程序(与DbContext一起使用),我收到此错误:

  

由于已经处理了DbContext,因此无法完成操作。

这是堆栈跟踪:

  

[InvalidOperationException:无法完成操作,因为DbContext已被释放。]

     

System.Data.Entity.Internal.InternalContext.CheckContextNotDisposed()+ 67

     

System.Data.Entity.Internal.LazyInternalContext.InitializeContext()+34

     

System.Data.Entity.Internal.Linq.DbQueryProvider.Execute(Expression expression)+22

     

System.Linq.Queryable.Any(IQueryable 1 source, Expression 1个谓词)+265

     

MyProject.MyRoleProvider.IsUserInRole(String username,String roleName)in ...

     

System.Web.Security.Roles.IsUserInRole(String username,String roleName)+263

     

MyProject.MyPrincipal.IsInRole(String role)in ...

     

System.Linq.Enumerable.Any(IEnumerable 1 source, Func 2谓词)+146

     

System.Web.Mvc.AuthorizeAttribute.AuthorizeCore(HttpContextBase httpContext)+200

     

System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext)+159

     

System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext,IList`1过滤器,ActionDescriptor actionDescriptor)+96

     

System.Web.Mvc.Async。 <> c__DisplayClass25.b__1e (AsyncCallback asyncCallback,Object asyncState)+446

     

System.Web.Mvc.Async。 WrappedAsyncResult`1.Begin (AsyncCallback回调,对象状态,Int32超时)+130

     

System.Web.Mvc.Async。 AsyncControllerActionInvoker.BeginInvokeAction (ControllerContext controllerContext,String actionName,AsyncCallback callback,Object state)+302

     

System.Web.Mvc。 <> c__DisplayClass1d.b__17 (AsyncCallback asyncCallback,Object asyncState)+30

     

System.Web.Mvc.Async。 WrappedAsyncResult`1.Begin (AsyncCallback回调,对象状态,Int32超时)+130

     

System.Web.Mvc。 Controller.BeginExecuteCore (AsyncCallback回调,对象状态)+382

     

System.Web.Mvc.Async。 WrappedAsyncResult`1.Begin (AsyncCallback回调,对象状态,Int32超时)+130

     

System.Web.Mvc。 Controller.BeginExecute (RequestContext requestContext,AsyncCallback callback,Object state)+317

     

System.Web.Mvc.Controller.System.Web.Mvc.Async。 IAsyncController.BeginExecute (RequestContext requestContext,AsyncCallback callback,Object state)+15

     

System.Web.Mvc。 <> c__DisplayClass8.b__2 (AsyncCallback asyncCallback,Object asyncState)+71

     

System.Web.Mvc.Async。 WrappedAsyncResult`1.Begin (AsyncCallback回调,对象状态,Int32超时)+130

     

System.Web.Mvc。 MvcHandler.BeginProcessRequest (HttpContextBase httpContext,AsyncCallback回调,对象状态)+249

     

System.Web.Mvc。 MvcHandler.BeginProcessRequest (HttpContext httpContext,AsyncCallback回调,对象状态)+50

     

System.Web.Mvc.MvcHandler.System.Web。 IHttpAsyncHandler.BeginProcessRequest (HttpContext context,AsyncCallback cb,Object extraData)+16

     

System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()+301

     

System.Web.HttpApplication.ExecuteStep(IExecutionStep step,Boolean& completedSynchronously)+155

正如您所看到的,MyProject.MyRoleProvider.IsUserInRole是异步调用的,我没有启动它,而是由MVC本身调用异步。所以我对它没有任何控制权。我的提供者是:

public MyRoleProvider(){     _context = MyIoCWrapper.GetService(); }

MyRoleProvider实例化时,HttpContext不为空,并且当IsInRole被调用时,HttpContext为空。 如果我想开始一个新的生命范围,它将只使用一次,如果MVC启动一个新的线程,我也将有一个新的DbContext。我很困惑找到一个解决方案。你有没有? 如何为所有后台线程启动新的生命范围 - 我启动它们或MVC启动它们?

1 个答案:

答案 0 :(得分:1)

您的问题实际上与异步运行控制器无关,但是控制对象生命周期的一般问题。

您可能在应用程序的web.config中注册了MyRoleProvider,或者可能通过代码注册了它。无论如何,MyRoleProvider是一个单例,在应用程序的生命周期中只有该类的一个实例。

然而MyRoleProvider依赖于生命周期较短的DbContext(在您的情况下为每个Web请求或混合),这意味着您无法在DbContext期间缓存MyRoleProverDbContext的生命周期,因为这会'促进'_context = MyIoCWrapper.GetService();的单身生活方式。 DbContext行似乎表示您正在缓存DbContext

在这种情况下,您必须在每个方法调用上解析IsUserInRole实例。相反,您的public bool IsUserInRole(String username, String roleName) { var context = MyIoCWrapper.GetService(); return context.Roles .Any(r => r.Name == roleName && r.User.Name == username); } 看起来像这样:

{{1}}