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; 
}