Is someone able to explain NHibernate's CallSessionContext, and contrast it to ThreadStaticSessionContext.
The best explaination I have been able to find, has been from the NHibernate documentation :
NHibernate.Context.CallSessionContext- current sessions are tracked by CallContext. You are responsible to
bind and unbind an ISession instance
with static methods of class
CurrentSessionContext.
NHibernate.Context.ThreadStaticSessionContext - current session is stored in a thread-static variable. This context
only supports one session factory. You
are responsible to bind and unbind an
ISession instance with static methods
of class CurrentSessionContext.
I am familiar with the WebSessionContext, as my usual use of NHibernate is in web applications. This time I am building a WCF service, to be hosted in IIS, and am trying to determine which implementation of ICurrentSessionContext is preferable.
I would like to know the implications of choosing one vs the other, both in this particular case (WCF service), and in general for future reference.
NHibernate 3 has a WCF-specific implementation, WcfOperationSessionContext
Related
I have some legacy code that used to open its own Sqlconnection. And I would now like to use the SqlConnection Nhibernate creates.
But I'd rather avoid to change the code a lot (DI, adding loads of settings, ...), so, Is there a simple (convienent) way to get the current Nhibernate session?
No. What is current NHibernate session anyway?
In a web application, each http request must work with its specific NHibernate session(s).
In a desktop application, each screen will probably use one session for each of their actions.
The NHibernate session is not supposed to be used as a singleton.
You should probably use your session factory to open a new NHibernate session in your legacy code then use its CreateSQLQuery method. Your session factory should usually have a singleton lifetime.
If you bound your NHibernate sessions to some context meaningful for your application (such as the HttpContext, CallContext), you may instead get it from there. Beware of cases which may cause contexts losses (async/await configured for not restoring context, asp.net thread agility (do not cause HttpContext losses but CallContext losses), ...).
I have a c# solution with 3 projects - Data, WCF and UI. The first one is a class library that talks to db. It's exposed via the second one, which is of type WCF Service Library - the reason for that is it will be exposed in third project - Asp.net app called UI - as a simple svc pointing to dll.
Just to point it out, I'm not using Repository pattern.
I need to have ISession for a WCF call (similiar to Session-per-request approach for asp.net). Can anyone share a solution that simply works? I don't want to use any IOC for that.
Use WcfOperationSessionContext (new in 3.0).
Once bound, your Data classes just have to use SessionFactory.GetCurrentSession().
Each call to service is associated with unique OperationContext. OperationContext doesn't have any store for custom objects but you can implement extension. By setting session in MessageInspector you can initiate NHibernate Session per call in centralized place and access your extended context in any operation.
Is Castle Windsor's Inteceptor mechanism considered to be a good/effective way of implementing the Unit of Work pattern?
My project involves Castle Windsor, the NHibernate Facility and of course NHibernate - all used in self-hosted WCF services.
Each service method normally requests from the Windsor container an instance of a helper class into which the WCF call is delegated. The helper class has an ISessionManager constructor argument which Windsor resolves via the NHibernate Facility.
The trouble is, the helper class is doing too much work. It has both logic and data access intermingled which means its difficult (virtually impossible) to test and difficult to read.
What I want is to re-arrange responsibilities
I don't want the WCF helper to know anything about transactions or sessions, so no ISessionManager constructor arg, no references to transactions and no ISession.
In order for the WCF helper to do data access, its going to have to rely on a new helper, dare I call it a DAO? or God forbid a repository, on which will be methods for fetching, querying, and possibly saving domain objects.
The problem with returning NHibernate proxied objects from a DAO is that if the session is closed before the entity is returned, any subsequent attempt to access collections on the domain object from the client code will result in an exception as the session is no longer there to be used to lazily fetch the required data. It's obvious really, but everyone new to NHibernate must hit this issue.
So if DAOs and Repos cant close the session, what does?
What I need is one NHibernate session per WCF service operation call, where several DAOs or Respositories can call OpenSession as much as they like, but they all get the same session, and ideally, any attempt to dispose the session would be ignored unless its the last Dispose. Not sure about the last bit, but maybe DAOs and repos just call ISessionManager.OpenSession and leave it to something else to flush and dispose the session.
I thought maybe I could use an interceptor which takes an ISessionManager, opens a session and starts a transaction, forwards the invocation, then if no exception occurs, commits the transaction and disposes the session, otherwise rolls back the transaction if any exception occurs.
Any thoughts?
So if DAOs and Repos cant close the
session, what does?session, what does?
Services own units of work, not DAOs. They demark units of work.
Spring manages transactions using AOP, so interceptors sound like a good bet for transaction management to me.
As far as sessions go, those are UI concepts, so it ought to be the web or desktop UI controller that opens the session, marshals services to fulfill use cases, and closes the session when it's complete.
Castle.Service.Transactions also ties well together with the rest of the castle stack and allow you to use AOP to handle transactions.
Have a look at v3!
https://github.com/haf/Castle.Services.Transaction
And the wiki there!
I also created a new NHibernate Facility:
https://github.com/haf/Castle.Facilities.NHibernate/wiki/NHibernate-Facility---Quick-Start
I have a c# library for my web application where I am using nhibernate.
The web application has the hibernate.cfg.xml file where I set:
current_session_context_class = web
I am using a nhibernateHelper class and a httpmodule to open and close the session on a per request basis.
I now need to use this library in a console application, what should I set the current_session_context_class value to be now?
There is a "thread" option that you can use. That will bind the current session to the thread.
For more on session management in desktop applications:
What is your session management strategy for NHibernate in desktop applications?
Ayendes MSDN article on NHibernate and desktop applications:
http://msdn.microsoft.com/en-us/magazine/ee819139.aspx
I've used nHibernate for both web and console apps, but never use this particular config setting.
I did some google-ing and found this:
Contextual Sessions
Excerpts:
Out-of-the-box, NHibernate 2.0.0 comes
with several implementations of this
interface:
NHibernate.Context.ManagedWebSessionContext
-current sessions are tracked by HttpContext. However, you are
responsible to bind and unbind an
ISession instance with static methods
on this class, it never opens,
flushes, or closes an ISession itself.
NHibernate.Context.CallSessionContext
-current sessions are tracked by CallContext. You are responsible to
bind and unbind an ISession instance
with static methods of class
CurrentSessionContext .
NHibernate.Context.ThreadStaticSessionContext
-current session is stored in a thread-static variable. This context
only supports one session factory. You
are responsible to bind and unbind an
ISession instance with static methods
of class CurrentSessionContext.
NHibernate.Context.WebSessionContext - analogous to ManagedWebSessionContext above, stores
the current session in HttpContext.
You are responsible to bind and unbind
an ISession instance with static
methods of class
CurrentSessionContext.
.....
...however, there are corresponding
short names: "managed_web", "call",
"thread_static", and "web",
respectively.
What's the simplest way to preserve a NHibernate ISessionFactory for web pages and web services?
I'll get into the Rhino Commons and Windsor this and that later. I'm looking for the basic concept.
Is this correct?
I've been trying to find guidance on how to deal with the ISessionFactory as simply as possible. I'm also looking for a solution that would work in both web pages and web services. The examples that I've seen deal with web pages and never touch the subject of web services. They start by building a Httpmodule that creates the ISessionFactory and store it in a static variable (e.g., Jeffery Palermo's HybridSessionBuilder (jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple/) or in the Summer of NHibernate's (www.summerofnhibernate.com see StaticSessionManager in Session 13). I've also noticed that despite the fact that ISessionFactory implements IDisposable nobody seems to be disposing of it. I guess they just let the garbage collector dispose of it when the web application ends, which would occur if IIS is recycled or the web site becomes idle.
If all this is true, the simplest thing would be to create some class that has a static variable that is used to store the ISessionFactory. This class would be instantiated and used by web pages and web services. Each time the class is instantiated, I would check to make sure that the static ISessionFactory variable is not null. If it is null, I recreate it. Thus, I keep the ISessionFactory alive by having something, either a web page or web service, within the web application create an instance of the class. The fact that the ISessionFactory is in a static variable means that it is shared by every instance of the class. Since the session factory is thread safe, this is ok. As long as I don't share ISessions, I'm golden. When nobody has an instance of this common class, the static variable is no longer referenced and garbage collection will destroy of the ISessionFactory .
Is this the basic principle behind keeping the ISessionFactory alive?
I think you have it mostly figured out.
The reason no one is disposing of the session factory is that, in general, you really don't want to. Building the session factory is an extremely expensive operation that can take many seconds, so you want to hold onto it for as long as possible. The .NET runtime will actually create a pool of HttpApplications and may create/dispose of them at will. So if you can store the session factory outside of the application, at the AppDomain scope, that is preferable since the factory will endure until the domain is recycled. Declaring the session factory as static will achieve this so that's why that is done; see the MSDN docs on static classes:
A static constructor is only called
one time, and a static class remains
in memory for the lifetime of the
application domain in which your
program resides.
So, if you make the session factory container static and never explicitly dispose of it, it will remain in memory until the AppDomain is recycled, maximizing the utility of that factory instance and the performance of your application.