Using NHibernate In Your Service Layer
Posted by Davy Brion on December 11th, 2009
I have an old post where i discuss how you can manage your NHibernate sessions in a service layer scenario. Now, the example of the service layer code in that post was pretty poor and people were asking for a better example. Hopefully, this post will do a better job at making sure everything is clear
First of all, the idea is to make sure that managing the NHibernate session (creating it, starting a transaction, committing or rolling back the transaction and closing the session) is taken care of automatically so you no longer have to worry about it. I also want to avoid passing the NHibernate session around all the time. This means that it will be created automatically when a request is sent to your service layer and stored in some place that will keep the instance alive during the handling of the service layer request. Every class that needs a reference to the current session (ideally only classes that deal purely with data access) will be able to retrieve it very easily, all in a thread-safe manner that can never be influenced by other concurrent requests.
First of all, you need something to wrap NHibernate’s ISessionFactory. I use the ISessionProvider for that:
public interface ISessionProvider
{
ISession Create();
}
public class SessionProvider : ISessionProvider
{
private readonly ISessionFactory sessionFactory;
public SessionProvider(string mappingAssemblyName)
{
Configuration configuration = new Configuration()
.Configure()
.AddAssembly(mappingAssemblyName);
sessionFactory = configuration.BuildSessionFactory();
}
public ISession Create()
{
return sessionFactory.OpenSession();
}
}
In my case, i configure the IOC container to pass the name of the assembly that contains the mappings to the constructor of the SessionProvider class. If you’re using this code directly in your application, you could just as well hardcode the name of the assembly here.
You’ll also need something that allows you to store and retrieve the NHibernate session for the duration of the current request. I use the IActiveSessionManager for that:
public interface IActiveSessionManager
{
ISession GetActiveSession();
void SetActiveSession(ISession session);
void ClearActiveSession();
bool HasActiveSession { get; }
}
public class ActiveSessionManager : IActiveSessionManager
{
private const string sessionKey = "_currentSession";
private readonly IRequestState requestState;
public ActiveSessionManager(IRequestState requestState)
{
this.requestState = requestState;
}
public ISession GetActiveSession()
{
if (Current == null)
{
throw new InvalidOperationException("There is no active ISession instance for this thread");
}
return Current;
}
public void SetActiveSession(ISession session)
{
if (Current != null)
{
throw new InvalidOperationException("There is already an active ISession instance for this thread");
}
Current = session;
}
public void ClearActiveSession()
{
Current = null;
}
public bool HasActiveSession
{
get { return Current != null; }
}
protected virtual ISession Current
{
get
{
return requestState.Get<ISession>(sessionKey);
}
set
{
requestState.Store(sessionKey, value);
}
}
}
This class will store the ISession instance in the current request state (definitely click on that link if you don’t know IRequestState yet).
Now we can create our own Unit Of Work. This is not a pure Unit Of Work because it doesn’t do any change tracking or anything like that, but it does take care of creating an NHibernate session (which does do change tracking and anything that a real Unit Of Work should do) and cleaning it up when the Unit Of Work is completed. Here’s my implementation:
public interface IUnitOfWork : IDisposable
{
void Clear();
void Flush();
ITransaction CreateTransaction();
ITransaction CreateTransaction(IsolationLevel isolationLevel);
}
public class UnitOfWork : Disposable, IUnitOfWork
{
private readonly IActiveSessionManager sessionManager;
private readonly ISession session;
private readonly bool isRootUnitOfWork;
public UnitOfWork(ISessionProvider sessionProvider, IActiveSessionManager sessionManager)
{
this.sessionManager = sessionManager;
if (sessionManager.HasActiveSession)
{
isRootUnitOfWork = false;
session = sessionManager.GetActiveSession();
}
else
{
isRootUnitOfWork = true;
session = sessionProvider.Create();
sessionManager.SetActiveSession(session);
}
}
public void Clear()
{
session.Clear();
}
public void Flush()
{
session.Flush();
}
public ITransaction CreateTransaction()
{
return CreateTransaction(IsolationLevel.ReadCommitted);
}
public ITransaction CreateTransaction(IsolationLevel isolationLevel)
{
if (session.Transaction != null && session.Transaction.IsActive)
{
throw new InvalidOperationException("nested transactions are not supported!");
}
return session.BeginTransaction(isolationLevel);
}
protected override void DisposeManagedResources()
{
if (isRootUnitOfWork)
{
if (session != null)
{
session.Close();
session.Dispose();
}
sessionManager.ClearActiveSession();
}
}
}
The idea is very simple. When the Unit Of Work is created, it asks the IActiveSessionManager if there is already an active session available. If not, it will create a new session through the ISessionProvider, and store it as the active session through the IActiveSessionManager. In the old implementation, the Unit Of Work would automatically create a new session in the constructor, but this obviously causes problems if you want to reuse a certain request handler from another request handler if they both depend on a IUnitOfWork instance. The IUnitOfWork interface doesn’t expose a lot of functionality but it’s all you need to manage your session in your service layer. It gives you the ability to create a transaction, clear the session and flush the session. When the IUnitOfWork is disposed, it will clean up the session and instruct the IActiveSessionManager to get rid of the session for this request.
Once you have this, you have all you need to prepare your service layer to take care of NHibernate session management automatically. I’m going to base the following service layer code example on Agatha (just because i think it’s the easiest way to implement a service layer
) but you can do exactly the same in your service layer. The important part is that you should configure your IOC container to inject a new instance of IUnitOfWork into the class that handles your service request. When the container injects the new instance, the NHibernate session will be created and stored in the IActiveSessionManager so there’s no more reason why you would have to do this yourself.
Now, i use the following class as the base class for all my request handlers that need NHibernate support:
public abstract class NhRequestHandler<TRequest, TResponse> : RequestHandler<TRequest, TResponse>
where TRequest : Request
where TResponse : Response
{
public IUnitOfWork UnitOfWork { get; set; }
protected override void DisposeManagedResources()
{
if (UnitOfWork != null) UnitOfWork.Dispose();
}
public override Response Handle(Request request)
{
using (ITransaction transaction = UnitOfWork.CreateTransaction())
{
Response response;
try
{
response = base.Handle(request);
transaction.Commit();
}
catch (Exception handlerException)
{
transaction.Rollback();
throw;
}
return response;
}
}
}
(Note: the real implementation contains a bit more logging but other than that this is the real thing)
If you don’t understand the whole request handling concept, please check out the first 3 posts in this series. Regardless of whether you’re using Agatha, your own Request/Response Service Layer or a classic (dare i say old-school?) service layer, the idea should be the same. Make sure this code is centralized in one place so you don’t have to repeat yourself all over your service layer code. Btw, in this case the IUnitOfWork instance is injected by the IOC container through Setter Injection instead of Constructor Injection. I’ve already discussed the reasons on why i prefer Setter Injection in this case here.
Now, you’re going to have some classes that will need to use an ISession instance to perform their tasks. I always create Repository classes for that, but the following approach would be similar for any other type of class which needs an ISession. Call them Data Access Objects, Data Access Classes or Sloppy Joes for all i care. Whatever you call these classes, they need a dependency on the IActiveSessionManager. Simply declare the IActiveSessionManager to be a dependency of your Sloppy Joe, i mean, Repository or DAO or whatever, like this:
public class Repository<T> : IRepository<T>
{
private readonly IActiveSessionManager activeSessionManager;
public Repository(IActiveSessionManager activeSessionManager)
{
this.activeSessionManager = activeSessionManager;
}
protected ISession Session
{
get { return activeSessionManager.GetActiveSession(); }
}
Now you can write request handlers like this:
public class GetCustomersRequestHandler : NhRequestHandler<GetCustomersRequest, GetCustomersResponse>
{
private readonly IRepository<Customer> repository;
public GetCustomersRequestHandler(IRepository<Customer> repository)
{
this.repository = repository;
}
public override Response Handle(GetCustomersRequest request)
{
var response = CreateTypedResponse();
response.Customers = ConvertToDtos(repository.FindAll(request.Criteria));
return response;
}
private CustomerDto[] ConvertToDtos(IEnumerable<Customer> customers)
{
// …
}
}
Obviously, this is a simple example but it works just as well for complex request handlers. Your NHibernate session is created and cleaned up automatically, without you having to write that code every single time. Each request handler will run in a transaction, and it will be committed or rolled back automatically without you having to do anything for it. And you only need to access the ISession instance in your Sloppy Joes.
Also keep in mind that you can also use the the ISessionProvider, IActiveSessionManager and IUnitOfWork in a purely web-based scenario as well if you want to.

December 11th, 2009 at 2:49 pm
i may be missing something here, but if one request handler needs the services of another request handler, an exception will be thrown because nested transactions are not supported right?
December 11th, 2009 at 2:52 pm
@Marco
it will work, because request handler A would call request handler B’s Handle(TRequest) method, which doesn’t create a new transaction. The Handle(Request) method (which does create the transaction) is only called by the Request Processor, unless you call it explicitly (which is never a good idea)
December 11th, 2009 at 2:58 pm
gotcha, i figured i was overlooking something!
December 11th, 2009 at 3:22 pm
have you worked with SessionFactory.GetCurrentSession() and CurrentSessionContext? I find this is much easier to manage.
December 11th, 2009 at 3:26 pm
@Jason,
never really used it, because it didn’t support WCF session context when i needed it. i did add it later though. But it won’t be available until NH 3.0 is out.
December 11th, 2009 at 5:58 pm
Davy, this posting is much appreciated! Between you, my friends Hudson, “how do i get out of this chicken shit outfit?”, and Robert, “Radio-Silence….”) I may actually be able to claim fraternity with such as you three again.
December 13th, 2009 at 6:20 am
I know this is all slightly out of the scope of Agatha, but it would be nice to have all of this code somehow included with it.
December 14th, 2009 at 10:40 am
[...] Using NHibernate In Your Service Layer – Davy Brion revisits the management of NHibernate Sessions in Service Layer projects with implementations of ISessionProvider, IActiveSessionManager and IUnitOfWork interfaces, along with the code to wire this solution into your application [...]
January 8th, 2010 at 2:58 pm
[...] Read: http://davybrion.com/blog/2009/12/using-nhibernate-in-your-service-layer/ [...]
January 13th, 2010 at 9:09 am
I’m not quite sure, why you have the UnitOfWork class? It’s seems that all it does is managing the session – which could just as well be done by the SessionManager. It’s seems simpler. Why do you introduce the UoW instead of just using the session directly?
January 13th, 2010 at 9:11 am
@Asger
i only want my Repositories to access the ISession directly… the UnitOfWork provides an abstraction that is typically easier to muck/stub during tests
January 16th, 2010 at 12:05 am
Davy – I am really, really learning how far I still have to go when I codewalk your material. I took the day off just to spend with Agatha. I do have one question regarding using Setter Injection on the UoW variable.
How do I configure that?
I have already created a boot strap class that inherits from container, and I register it with:
Register(Lifestyle.Transient).
However, when I get to the part of Handler, it is always null. Would it have anything to do with RequestState? I am using the WcfRequestState implementation.
Cheers!
C
January 16th, 2010 at 12:06 am
I should have known the Angle Brackets wouldn’t post. I think I remember Steve Boehlen having the same issue earlier
January 16th, 2010 at 12:40 am
Never mind…I had not tested my Session Provider (I added a string to the constructor, which was not being provided). This caused that object to not create and that apparently bubbled up. Once I removed the string and retested, the Setter Injection works.
Eyes going squirrley…need pizza and beer.
Cheers
C
January 16th, 2010 at 4:06 pm
@Chuck
keep in mind that you’re not obligated to use Setter injection with this… if you add the IUnitOfWork as a constructor dependency, it will work as well. Though you’d have to put it in the constructor of each derived class as well.
March 10th, 2010 at 11:16 pm
I really want to thank you again for this article. This have made a huge difference just by walking the code of this and the other articles.
again, much appreciated. If/when you get to chicago i at least owe a coffee.
KES
March 11th, 2010 at 7:13 am
i’ll have the tall cappuccino
March 11th, 2010 at 2:59 pm
Consider it done! i’ll give you my cell off line just send me an Email!
April 5th, 2010 at 12:06 pm
Davy, I am not sure if there’s a short or long answer to this. But any pointers would be really appreciated. My architecture at works requires a web app and a windows app to talk to the application server via WCF. The Application server being where all the Data access and Service libraries live. I intend to implement N-hibernate into the project. But wanted to get some pointers if your approach above is recommended for Web and Windows clients alike when sending and receiving data via WCF? Great article by the way., your style of blogging is really clear and concise. Helps a great deal in understanding and working towards a better development repertoire.
Thanks!
April 5th, 2010 at 5:35 pm
[...] Comments Afif on Using NHibernate In Your Service LayerDavid Boike on MSDTC Woes With NServiceBus And NHibernateForcibly creating a distributed .NET [...]
April 5th, 2010 at 5:37 pm
@Afif
i’ve tried to answer your question in this post… i hope it helps
April 29th, 2010 at 1:03 pm
Thanks for the post! Just want to mention that NHibernate is good but it has some drawbacks as well. For example it cannot handle ASP.NET web gardens. So it is better to use a distributed caching product as a 2nd level cache. There are some third party caches providers like NCache, which is a mature and well known distribute in-memory caching solution, offer appliance for NHibernate 2nd level caching without any code change.
June 2nd, 2010 at 7:18 am
Thank you for sucha great post . If possible if you can attach a sample working solution with your post . I have also read “Why You Shouldn’t Expose Your Entities Through Your Services”. Great information and really out of the box thinking .
August 21st, 2010 at 6:32 pm
Davy,
As always, excellent stuff.. I am trying to apply your ideas to my current project, but I have hit a problem on the way… The thing is I’m doing a WinForms application, with a session-per-presenter strategy (in this case, it means one per form).. Now my repositories etc. need to access the session from the currently active form, but I am not sure how to loosely obtain a reference to the currently active form’s session..
Any ideas?
From your blog it seems you mostly deal with WCF/WPF/silverlight and asp.net, I understand that this is perhaps a little outside your area, but maybe you could sketch a way you would do it, where you tasked with creating such an application..
August 22nd, 2010 at 12:33 pm
@Morten
I’ve never used the session-per-presenter strategy, nor would i recommend it actually.
What i would do in your scenario, would be to use an in-process Agatha service layer. It wouldn’t use WCF, it would run completely in process, but you would have a completely separated service layer from your presentation layer and you could reuse all of the NHibernate related tricks that you find on this blog
August 22nd, 2010 at 12:55 pm
Yeah that makes sense… Would this be sort-of a session-per-request scenario then?
August 22nd, 2010 at 12:56 pm
yup
or you could use a session per batch of requests if you want