In this post I will intent to describe a “new” pattern for NHibernate session management.
This pattern born some years ago, with another name “session-per-UseCase”, when I looking for a pattern to manage nh-sessions in Win-Form applications. The first implementation was not so clear and, before make it public, I have continued looking for some, well described, existing pattern. Two or three moths ago I was involved in another WinForm application, using NHibernate as persistence-layer, and I have re-begun the search for a pattern for session-handling in a rich-client application. This time my exigencies was something different because what I really want is a pattern to manage the session in complex applications even in web. By “complex-application” I mean an application where business-transactions involving more than one request is the norm and not the exception (for example a ERP of a big company). Using our best friend, Google, I find some few words about a pattern, used in JAVA, named “session-per-application-transaction” but his implementation is not so clear and is wired to some JAVA-world feature… unusable for me.
When you read something about NHibernate-session-management is because we want abstract/”aspect” NH-session’s stuff from the code are using it. In general, or I hope so, you are using the session in something like a DAO/Repository and, in a use-case, you are calling more than one DAO/Repository. Open a new session in each DAO/Repository is an anti-pattern called session-per-call (or very closer to it). What we are searching is something to manage the session in an high-layer but without wire that layer with NHibernate. In a WEB environment it is pretty easy because we can manage the session using an implementation of a IHttpModule, or in the HttpApplication, “intercepting” the request (two patterns mentioned here). In a winForm, or WPF, aplication it is not so clear where the abstraction have place. In this post I will use an “artifact” named Model to represent the “abstraction-point” (in my mind the Model is the business-object that are using DAOs/Repository and domain-entities); in an MVC based application, probably, the abstraction have place in the Controller.
Perhaps you have idea about what is a “business-transaction” in your application but, what mean “conversation” ?
To describe the conversation I have imagined a chat between two persons. A chat may Start, Pause, Resume, and End. By “End” I mean: the end with some formal conclusion. Not all chats are terminated with “some formal conclusion” so, an event like Abort is needed. Resuming, in a conversation we may use five actions: Start, Pause, Resume, End, Abort. When I’m working in my PC, in general, I have more than one started chat, with more than one person. In my IM client, each chat is identified by an open form. In each chat I’m chatting about one specific matter, that mean that each chat have a specific context.
Resuming my conversation have: Id and Context properties, Start, Pause, Resume, End, Abort actions.
Can I apply the same concept to a persistence-conversation ?
Let me try…
First of all I have tried it using pure ADO.NET. In the ADO.NET scenario the Start and Resume of the conversation open a DbConnection and begin a DbTransaction, the Pause commit the DbTransaction and close the DbConnection; the End open a DbConnection, begin a DbTransaction, execute all pending db actions register in the UoW, commit the DbTransaction, close DbConnection, Dispose the UoW (obviusly I don’t spent so much time writing a good implementation of a PersistenceLayer nor UoW).
The Conversation with NHibernate
In NHibernate we have a well know and well described pattern named long-session (aka session-per-conversation). The description of the pattern is available in NHiA. For brevity here is the picture (extracted from Hibernate site)
As you can see there are various similar concepts between the session-per-conversation and Conversation-per-Business-Transaction. In Conversation-per-Business-Transaction there is one main difference: the Conversation is not a conceptual abstract description of what are happening but it is an interface with its concrete implementation.
To better understand let me explain what happen in Conversation-per-Business-Transaction:
- Context: one object of the conversation context is the session (or better all sessions of all sessionFactories we are managing in a multi-RDBMS application).
- Start : open a new session and hold it in the conversation-context (FlushMode.Never).
- Resume : begin a nh-transaction
- Pause : commit the nh-active transaction
- End : begin a nh-transaction, Flush the session, commit the transaction
- Abort : Close the session without Flush it
These are the base concepts behind the pattern.
If you want see one implementation of the pattern, even using Castle.Windsor to solve AOP, you can download uNhAddIns. I hope to have the time to write something more about the actual implementation soon.