8

我有一个MVC3项目,使用Ninject,实体框架和单位工作模式与服务层。Ninject范围问题与任务/线程

我AsyncService类有启动一个后台任务,作为一个例子,将用户添加到用户资料库的功能。 我目前的问题是,在我得到DbContext已被处置的错误之前,任务只能正确运行几秒钟。 我的数据库上下文,与Ninject的InRequestScope()注入似乎被处置,因为InRequestScope()将其绑定到HttpContext。

我读过有关InThreadScope(),但我不知道如何正确地执行它在我的MVC项目。

我的问题是:什么是在我的任务中使用Ninject的正确方法?

public class AsyncService 
{ 
    private CancellationTokenSource cancellationTokenSource; 
    private IUnitOfWork _uow; 
    public AsyncService(IUnitOfWork uow) 
    { 
     _uow = uow; 
    } 
    public void AsyncStartActivity(Activity activity) 
    { 
    ...snip... 
     this.cancellationTokenSource = new CancellationTokenSource(); 
     var cancellationToken = this.cancellationTokenSource.Token; 
     var task = Task.Factory.StartNew(() => 
      { 
       foreach (var user in activity.UserList) 
       { 
        this._uow.UserRepository.Add(new User() {UserID = user}); 
       } 
       this._uow.Save(); 
      }, cancellationToken); 
    ...snip... 
    } 
} 

回答

5

InRequestScope“d对象Dispose d在一个请求结束,因此它不能在这种情况下被使用。 InThreadScope也不适合,因为这将重用UoW的几个任务。

什么可以做,虽然是声明你AsyncService作为内使用NamedScope扩展的所有对象的范围界定对象。

http://www.planetgeek.ch/2010/12/08/how-to-use-the-additional-ninject-scopes-of-namedscope/

+3

是否有一个示例代码?杰森,你能在哪里工作?我遇到了同样的问题,并且下面的链接没有帮助。 –

+0

我有这个相同的问题,我很想看到这个场景的一些示例代码。 –

0

这是我在过去使用ChildKernel插件使用的凌乱的解决方案(我想命名的范围将更加清洁)。基本上我创建一个子内核,并将与UoW有关的所有内容都作为子内核中的单例。然后,我为每个任务创建一个新的子内核,处理UoW,并提交或回滚。

IAsyncTask是被1种方法的接口,Execute()

private Task void ExecuteTask<T>() where T:IAsyncTask 
{ 

     var task = Task.Factory.StartNew(() => 
              { 
      var taskKernel = _kernel.Get<ChildKernel>(); 
      var uow = taskKernel.Get<IUnitOfWork>(); 
      var asyncTask = taskKernel.Get<T>(); 

      try 
      { 
       uow.Begin(); 
       asyncTask.Execute(); 
       uow.Commit(); 
      } 
      catch (Exception ex) 
      { 
       uow.Rollback(); 
       //log it, whatever else you want to do 
      } 
      finally 
      { 
       uow.Dispose(); 
       taskKernel.Dispose(); 
      } 
     }); 
     return task; 
}