In the context of a windows web service that's meant to run jobs, we try to reuse the NHibernate DAL we developed for the web application.
For session management we have two options, each one having its advantages and drawbacks:
Stateful session
- Going to grow a lot as it keeps track of everything (L1/session cache)
- Needs to be carefully closed, session disposal doesn't seem to be enough to clear L1 cache (what I noticed using memory profiler)
Stateless Session
- Currently fails to reuse mappings. All bags declared with "lazy=true" ends up with the following exception (even though the session has not be closed):
Initializing [...] failed to lazily initialize a collection of role: [...], no session or session was closed
Obviously, we cannot update the mappings (they are shared with the web app) with lazy="false", it's gonna be a huge drawback for performances
- Cannot interact with L2 cache: when shared L2 cache will be deployed, the service will be unable to invalidate L2 cache data in order for web application to have fresh up-to-date data
NHibernate has proven to be good until now, we have successfully used stateful session and NHibernate LINQ it in a web context, with structuremap for dependency injection.
My questions are:
- Are there any good solutions to use NHibernate in a long running thread?
- I'd prefer to use stateful session, but how to avoid memory leak?
Problem solved! There were actually a couple of problems.
First one was about instances' scope, and multi-threading:
new HybridLifecycle().FindCache().DisposeAndClear();. It will cause the session attached to the thread to close and dispose.ThreadStaticvariable to keep a reference to the object cache. So the trick is to call StructureMap's ObjectFactory within the thread. Initially, in our application, a main thread was responsible for creating new threads, and call the ObjectFactory. That's the major mistake we did, and were indeed unable to clean the threads once their job was done.Session type:
Important remark: be careful to instantiate NHibernate NHibernate Session Factory only once!
When NHibernate instances are managed carefully, there is no memory leak.