12

W środowisku MVC/WebAPI użyłbym InRequestScope do wiązania DbContext.Ninject - W jakim zakresie DbContext powinien się wiązać, gdy RequestScope jest bez znaczenia?

Jednak obecnie pracuję nad rolą aplikacji Konsola/Usługa systemu Windows/Azure (nie ma znaczenia, nie ma zasięgu żądania strony), która okresowo tworzy numer Tasks, który działa asynchronicznie. Chciałbym, aby każde zadanie miało swój własny DbContext, a ponieważ zadania uruchamiane są na ich własnym wątku, próbowałem powiązać DbContext przy użyciu InThreadScope.

Niestety, zdaję sobie sprawę, że DbContext nie jest usuwany po zakończeniu zadania. W rzeczywistości wątek powraca do puli wątków, a gdy przypisano mu nowe zadanie, ma już DbContext, więc DbContexts pozostaną żywe na zawsze.

Czy istnieje sposób, w jaki można użyć InThreadScope, czy też powinienem użyć innego zakresu? W jaki sposób ThreadScope może być używany, gdy wątki wracają z ThreadPool co jakiś czas?

+0

Zauważyłeś, że [na wątek Styl życia uważany jest za szkodliwy] (https://stackoverflow.com/questions/14591422/why-is-perthreadlifetimemanager-used-in-this-example). – Steven

+0

@Steven Tak, rozumiem. Jak wdrożyć niestandardowy zakres (lub inne rozwiązanie)? –

+1

Nie powinieneś w ogóle używać zakresu. Użyj fabryki, aby utworzyć DbContext (który jest w zasadzie * jednostką pracy *) - i przekazać ją w razie potrzeby. Jeśli oprogramowanie pozostaje tak proste, jak to opisałeś, możesz także użyć nazwanego zakresu (zdefiniowanego przez zadanie i powiązać DbContext 'InNamedScope'). Ale to nie jest przyszły dowód, na przykład, gdy chcesz utworzyć DbContext poza zadaniem lub gdy chcesz mieć wiele (sekwencyjnych) DbContext w jednym zadaniu, ... itd. – BatteryBackupUnit

Odpowiedz

1

Jeśli zdecydujesz się iść z niestandardowym zakresie, rozwiązaniem jest:

public sealed class CurrentScope : INotifyWhenDisposed 
{ 
    [ThreadStatic] 
    private static CurrentScope currentScope; 

    private CurrentScope() 
    { 
    } 

    public static CurrentScope Instance => currentScope ?? (currentScope = new CurrentScope()); 

    public bool IsDisposed { get; private set; } 

    public event EventHandler Disposed; 

    public void Dispose() 
    { 
     this.IsDisposed = true; 
     currentScope = null; 
     if (this.Disposed != null) 
     { 
      this.Disposed(this, EventArgs.Empty); 
     } 
    } 
} 

Oprawa:

Bind<DbContext>().To<MyDbContext>().InScope(c => CurrentScope.Instance) 

i wreszcie:

using (CurrentScope.Instance) 
{ 
    // your request... 
    // you'll get always the same DbContext inside of this using block 
    // DbContext will be disposed after going out of scope of this using block 
}