My project is structured by services and repositories (all repositories share the db context). In one of my service layers, I have an asynchronous method that writes to the database using a repository. The web request will finish and dispose of the context before this method can get to use it. I tried to understand NamedScopes as stated in this answer. I still can't seem to understand how to implement it. I'll show how my project is structured and hope someone can help me at the code level.
Bindings
private static void RegisterServices(IKernel kernel)
{
//dbcontext
kernel.Bind<EntityDatabaseContext>().ToMethod(context => new EntityDatabaseContext()).InRequestScope();
//unit of work
kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope();
//repositories
kernel.Bind<IRepository<Account>>().To<Repository<Account>>().InRequestScope();
//services
kernel.Bind<IAuthenticationService>().To<AuthenticationService>().InRequestScope();
}
AuthenticationService uses constructor injection
public AuthenticationService(UnitOfWork unitOfWork, IRepository<Account> accountRepository){}
A method inside my AuthenticationService
//this is a background process
public Task SomeMethodAsync(string text)
{
//spin it off into a new task
return Task.Factory.StartNew(() => SomeMethod(text));
}
SomeMethod
makes use of accountRepository
. Please tell me if anymore information is needed. Please help me with the threading issue, if NamedScopes is the solution, how do I implement it in my case?
Basically, a background process is being executed and it is using a context that is being disposed of by ninject due to the request scope.
You should be aware that running background threads can cause you many problems. IIS can decide to recycle the app pool at any time which will terminate your thread immediately (or it doesn't execute in some cases at all) leaving your application in an inconsistent state.
http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx
The easiest and least error prone wayto run asyncronous operations is to implement a windows service and delegate those async operations to the windows service e.g. using MSMQ.
If you still want to go the hard way then read about HostingEnvironment.RegisterObject
and IRegisteredObject
to prevent these inconsistent situations.
The Ninject part is quite easy. Just create some job processor class e.g. MyJobProcessor
taking all required dependencies to execute the task. It should implement INotifyWhenDisposed
. The easiest way to do so is to derive from DisposeNotifyingObject
.
public class MyJobProcessor : DisposeNotifyingObject, IRegisteredObject
{
public void Execute() { ... }
public void Stop(bool immediate) { ... }
}
Inject this processor to the controller and let the Task start it and dispose it when it has finished its work.
Task.Factory.StartNew(() =>
{
try
{
processor.Execute();
}
finally
{
processor.Dispose);
}
});
Specify that it is the scope for its dependencies.
Bind<MyJobProcessor>().ToSelf().Named("MyJobProcessor").DefinesNamedScope("MyJobProcessorScope");
Bind<IUnitOfWork>().To<UnitOfWork>().WhenAnyAnchestorNamed("MyJobProcessor").InNamedScope("MyJobProcessorScope");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With