8

Ich habe ein MVC3-Projekt, das Ninject, Entity Framework und das Unit of Work-Muster mit einer Service-Schicht verwendet.Ninject Scope Problem mit Aufgaben/Threads

Meine AsyncService-Klasse hat eine Funktion, die eine Hintergrundaufgabe startet, die beispielsweise Benutzer zum Benutzer-Repository hinzufügt. Mein aktuelles Problem ist, dass die Aufgabe nur für ein paar Sekunden korrekt ausgeführt wird, bevor ein Fehler auftritt, dass der DbContext entsorgt wurde. Mein Datenbankkontext, der mit Ninject's InRequestScope() injiziert wird, scheint entsorgt zu werden, da InRequestScope() ihn an HttpContext bindet.

Ich habe über InThreadScope() gelesen, aber ich bin mir nicht sicher, wie es in meinem MVC-Projekt richtig zu implementieren.

Meine Frage ist: Was ist der richtige Weg Ninject in meiner Aufgabe zu verwenden?

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

Antwort

5

InRequestScope ‚d Objekte sind Dispose d am Ende einer Anfrage, so dass es in diesem Fall nicht verwendet werden kann. InThreadScope passt auch nicht als das würde die UoW für verschiedene Aufgaben wiederverwenden.

Sie können jedoch Ihre AsyncService als Scoping-Objekt für alle Objekte innerhalb der NamedScope-Erweiterung deklarieren.

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

+3

Gibt es ein Codebeispiel? Jason, wo kannst du es zur Arbeit bringen? Ich habe das selbe Problem und das Folgen des Links hat nicht geholfen. –

+0

Ich habe das gleiche Problem, ich würde gerne einen Beispielcode für dieses Szenario sehen. –

0

Dies ist eine schmutzige Lösung, die ich in der Vergangenheit verwendet haben die ChildKernel Plugin (ich glaube, Named Umfang würde viel sauberer). Im Grunde erstelle ich einen Child-Kernel und lege alles, was zur UoW ​​gehört, als Singleton im Child-Kernel an. Ich erstelle dann einen neuen Kindkern für jeden Task, handle den UoW und Commit oder Rollback.

IAsyncTask ist eine Schnittstelle mit 1-Methode, 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; 
}