I have been racking my brain on and off with this for a few weeks now... What I currenlty have is this:
- A bunch of
*Service
classes - All of these depend on different
*Repository
classes that access database via EF - To allow Unit Testing a derivate of
DbContext
is injected into repositories. (so I can not useusing
to dispose of the contexts)
To correctly dispose of the EF contexts that are injected I could run my dependency tree in InRequestScope()
or in a simple custom scope - InScope(c => new object())
on the top level and in InParentScope()
on all other levels.
Both of these approaches would create and dispose a lot of objects during each request. In addition we are talking about a single page application so that 95% of the queries (50 or so) will be executed during 2 requests so InRequestScope()
seems not to be a good idea. Also the *Service
classes hold no state and thus could be InSingletonScope()
and would minimize the amount of object creation.
The Question
Is it possible to have parent *Service
and *Repository
classes in InSingletonScope()
and somehow inject EF DbContext
in a scope that will return a new instance each time it is accessed and will honor IDisposable
using NInject?
I know that dependencies are injected while objects are created but could this still be somehow managed?
No, it's not possible. If you think about it, you should understand why.
A singleton object will exist for the lifetime of the application. An InRequestScope object lives for the lifetime of a request. Since your singleton repository will live forever, and it will hold a reference to your DbContext (because it's a dependency), that means the dbcontext cannot be garbage collected without your repository having some mechanism to release it.
Even if you did supply such a mechanism, you'd have to have another mechanism to re-acquire a new instance on the next request, because a new singleton repository will not be created (and thus it's constructor will not be called, and thus it's dependencies will not be resolved, and thus it will not be able know about the new dbcontext).
So, in effect, making an InRequestScope object a dependency of a singleton object would effectively make the InRequestScope object a singleton, or else the object will be disposed out from under the singleton and that could be bad..
Also, I beg to differ with you on the fact that your repositories DO have state. The state is the DbContext itself. Since a Singleton is an application wide static instance, you give the same instance to all users using your app, which would mean it would also give the same DbContext, which is a huge no-no, since your users would stomp all over each others DbContext state.
Your services are also, likewise, stateful because they have repositories, which as I've just pointed out have DbContexts, which are stateful.
What you want to do is simply make your Services, repositories, and DbContexts all InRequestScope.
I fail to understand why this approach would "create lots of objects during each request". The whole point is that it only creates one instance of each object type per request.
来源:https://stackoverflow.com/questions/18203401/ninject-is-it-possible-to-have-parent-object-in-singletonscope-and-child-in-tra