The Inquisitive Coder – Davy Brion's Blog

Trying to walk that thin line between intelligence and ignorance

Managing your NHibernate Sessions

Posted by Davy Brion on June 22nd, 2008

Note: you can find a more recent post on this concept here.

I was working on my northwind sample application (which i’ll post about as soon as i get something that’s worth showing) and i was struggling to find a clean way to manage my NHibernate sessions. I wanted a way to create a session once you enter the service layer, and that session should be available transparently to the repository implementations without actually having to constantly pass it around. But i didn’t just want to store it somewhere and have all the classes that needed the current session get it directly from that place. Also, i didn’t want the current session to be available to everyone. Another important requirement was to have maximum flexibility for writing tests. I could just use Rhino-Commons’ implementations of the UnitOfWork and Repository patterns and be done with it, but where’s the fun in that? And since this application is mostly a learning experience i figured i should try to write this myself. After a bit of searching and experimenting, i finally came up with a way that i’m happy with (for now anyways). Let’s have a look.

To illustrate what i want, take a look at this made-up method in my service layer:

        public ProductCategoryDTO[] GetAllProductCategories()

        {

            using (ISession session = GetNewSession())

            {

                var repository = GetProductCategoryRepository();

                var categories = repository.GetAllProductCategories();

                return categories.ToDTOs();

            }

        }

This is just some example code, it doesn’t even work. But it’s kinda what i want… The thing is, i don’t want to deal directly with the ISession type in the service layer, but i do want the ProductCategoryRepository to use the ISession that is created within the context of this method call.

NHibernate’s ISession type is an implementation of the Unit Of Work pattern. I don’t want to use the ISession directly in my service layer because i want something that is a bit more high-level. Basically just something that would allow me to work within an NHibernate session, and provide me with the ability to flush changes to the database whenever i want to. And obviously, i want it to allow me to create a transaction as well. So i came up with the following unit of work interface:

    public interface IUnitOfWork : IDisposable

    {

        /// <summary>

        /// Flushes any changes that haven't been executed yet

        /// </summary>

        void Flush();

 

        /// <summary>

        /// Creates an ITransaction instance with the ReadCommitted isolation level

        /// </summary>

        /// <returns></returns>

        ITransaction CreateTransaction();

 

        /// <summary>

        /// Creates an ITransaction instance with the given isolation level

        /// </summary>

        /// <param name="isolationLevel"></param>

        /// <returns></returns>

        ITransaction CreateTransaction(IsolationLevel isolationLevel);

    }

This interface pretty much offers me anything i’m concerned with in my service layer. The real implementation would do a bit more though… It has to create an NHibernate session and make it available to the repositories in a clean way. Here’s the thing though… the repositories have a completely different lifetime than the NHibernate sessions. The NHibernate session has to be created when we enter a service method, and it has to be valid within the scope and context of the execution of that service method. The repositories however stay alive for the lifetime of the application so they can’t just hold a reference to an NHibernate session. Every time you call a method of a repository, it has to find out which session it should use, which is the session that is being used in the context of the current service method call. Now, we could always pass around the session but that really doesn’t look good and is cumbersome. So i basically need something that gives me access to the active nhibernate session:

    public interface IActiveSessionManager

    {

        /// <summary>

        /// Returns the active ISession for the current thread. Throws exception if there's

        /// no active ISession instance

        /// </summary>

        /// <returns></returns>

        ISession GetActiveSession();

 

        /// <summary>

        /// Sets the active ISession for the current thread. Throws exception if there's

        /// already an active ISession instance

        /// </summary>

        /// <param name="session"></param>

        void SetActiveSession(ISession session);

 

        /// <summary>

        /// Clears the active ISession for the current thread.

        /// </summary>

        void ClearActiveSession();

    }

That gives me the ability to retrieve and set the active session on a per-thread basis. After all, a service method call will be handled by one thread, so setting the active session for that current thread is a convenient way to store the session.

Now i still need something that takes care of creating the NHibernate sessions:

    public interface ISessionFactory

    {

        /// <summary>

        /// Creates a new ISession instance

        /// </summary>

        /// <returns></returns>

        ISession Create();

    }

Ok, so what do we have so far? An interface to define the functionality that a UnitOfWork should offer at the service level. An interface to store/retrieve the active session on the current thread, and finally, an interface to actually create the NHibernate session. Let’s start looking at the real implementations. Here’s the code to the SessionFactory class:

    public class SessionFactory : ISessionFactory

    {

        private readonly NHibernate.ISessionFactory sessionFactory;

 

        public SessionFactory()

        {

            Configuration configuration = new Configuration()

                .Configure()

                .AddAssembly("Northwind");

 

            sessionFactory = configuration.BuildSessionFactory();

        }

 

        public ISession Create()

        {

            return sessionFactory.OpenSession();

        }

    }

Pretty straightforward… it initializes NHibernate and gives us the ability to ask for new sessions. So how are we going to make these sessions available to our repositories? Through the ActiveSessionManager class of course:

    public class ActiveSessionManager : IActiveSessionManager

    {

        [ThreadStatic]

        private static ISession current;

 

        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;

        }

    }

It basically just stores the session in a ThreadStatic field, which means that each thread will have a different static reference for this field. So if we set the active session through the SetActiveSession method in thread X, and thread Y also sets an active session, the GetActiveSession method will return the correct session instances for each thread.

So now we have everything we need to create our UnitOfWork class:

    public class UnitOfWork : Disposable, IUnitOfWork

    {

        private readonly IActiveSessionManager activeSessionManager;

        private readonly ISession session;

 

        public UnitOfWork(ISessionFactory sessionFactory, IActiveSessionManager activeSessionManager)

        {

            this.activeSessionManager = activeSessionManager;

            session = sessionFactory.Create();

            activeSessionManager.SetActiveSession(session);

        }

 

        protected override void DisposeObjects()

        {

            if (session != null)

            {

                session.Close();

                session.Dispose();

            }

        }

 

        protected override void ClearReferences()

        {

            activeSessionManager.ClearActiveSession();

        }

 

        public void Flush()

        {

            session.Flush();

        }

 

        public ITransaction CreateTransaction()

        {

            return CreateTransaction(IsolationLevel.ReadCommitted);

        }

 

        public ITransaction CreateTransaction(IsolationLevel isolationLevel)

        {

            return session.BeginTransaction(isolationLevel);

        }

    }

When the UnitOfWork is created, it receives an ISessionFactory instance, and an IActiveSessionManager instance. It then creates a new session through the ISessionFactory and uses the IActiveSessionManager to make sure that session is the active session for the current thread. When the UnitOfWork is disposed, it closes and cleans up the session and it also uses the IActiveSessionManager to clear the active session for the current thread. Oh and it obviously also provides implementations for what it is we actually need in our service layer: flushing the changes whenever we want and creating transactions.

The ISessionFactory and IActiveSessionManager instances should stay alive as long as the application is alive. But as you could see in the implementations of those types, we didn’t write any code to deal with their lifetimes. I’m actually relying on my IoC container for that. In the class where my container is set up, you’ll find the following code:

        private static void RegisterUnitOfWorkComponents()

        {

            Register(Component.For<ISessionFactory>()

                .ImplementedBy<SessionFactory>().LifeStyle.Singleton);

            Register(Component.For<IActiveSessionManager>()

                .ImplementedBy<ActiveSessionManager>().LifeStyle.Singleton);

            Register(Component.For<IUnitOfWork>()

                .ImplementedBy<UnitOfWork>().LifeStyle.Transient);

        }

ISessionFactory and IActiveSessionManager are registered as singleton instances, so whenever these types are requested, the same instances will be returned. The IUnitOfWork type is registered with a transient lifetime, so whenever it is requested, the container will create a new UnitOfWork class and pass the ISessionFactory and IActiveSessionManager instances to the constructor.

Right, we’ve taken care of creating the session, associating it with the current thread and making it available in a nice and clean way. Now we actually have to make sure our repositories can use it. In the base repository implementation, you can find the following code:

        private readonly IActiveSessionManager activeSessionManager;

 

        public Repository(IActiveSessionManager activeSessionManager)

        {

            this.activeSessionManager = activeSessionManager;

        }

 

        protected ISession Session

        {

            get { return activeSessionManager.GetActiveSession(); }

        }

Whenever a repository needs a session, it just needs to use the protected Session property and it will get the session that is associated with the current thread.

So now we can rewrite our made-up service method from earlier to the following:

        public ProductCategoryDTO[] GetAllProductCategories()

        {

            using (Container.Resolve<IUnitOfWork>())

            {

                var repository = Container.Resolve<ProductCategoryRepository>();

                var categories = repository.GetAllProductCategories();

                return categories.ToDTOs();

            }

        }

We know that the NHibernate session will be created, and more importantly, that it is not just globally accessible to everyone. It can only be accessed when you have a reference to an IActiveSessionManager instance. We also don’t need to pass around the session all the time so our code is a bit more concise, showing only the intent of what we’re trying to do without distracting us with details that are not relevant to that intent. We also have a lot of flexibility to write tests… i can write tests for my repositories without having to create a UnitOfWork… i can simply pass a fake IActiveSessionManager to my repositories when i’m testing them and have it return the session that i’m using for my test. All in all, this approach offers me with a lot of advantages, without ugly disadvantages. Well, at this moment i don’t really see any disadvantages so if you do see some, please let me know :)

35 Responses to “Managing your NHibernate Sessions”

  1. Bill Pierce Says:

    I realize the code is illustrative for the sake of clarity. In your production code is Container.Resolve ubiquitous throughout your project?

    I’m also a big fan of removing knowledge of ITransaction from my code in UnitOfWork (also taken from Rhino commons)

    public void Transact(Action transactional)
    {
    if (session.Transaction.IsActive)
    {
    transactional();
    }
    else
    {
    using( ITransaction transaction = session.BeginTransaction() )
    {
    transactional();
    transaction.Commit();
    }
    }
    }

  2. Davy Brion Says:

    I do have a static Container class which wraps a few of the Windsor container methods, but i only use it in my service layer, or in my asp.net pages to retrieve components. In all other places i try to get everything injected.

    as for the transaction stuff… i’ve seen that approach and while i like it, i’m trying not to go overboard with passing Action or Func references so i haven’t gone down that road yet (so far). I’m actually thinking of going with a [IsTransactional] PostSharp attribute to decorate my service methods.

  3. Johnny Hall Says:

    Nice. Do you have a view on how well this approach will integrate with WCF?

    I’ve found integrating NH (specifically Session/SessionFactory management), IoC and WCF to be *challenging* to say the least.

    At the moment, I’m utilising a [UnitOfWorkContext] attribute to manage the Session, which essentially makes using IoC impossible. I’ll definitely revisit the work I’ve cobbled together so far to look at this approach.

  4. Davy Brion Says:

    My WCF service methods look like the one that is shown in the post, so they can play along nicely… actually, WCF and NH don’t even know about each other here, because i keep NHibernate contained behind the service layer.

    Btw, you could do exactly the same with your UnitOfWorkContext attribute like i do with my using statement. My UnitOfWork class simply creates a session and associates it with the current thread. You could do the exact same thing, only you’d use the IoC container within the attribute code.

  5. Johnny Hall Says:

    Excellent. I’m finally seeing the light at the end of the NH/WCF/IoC integration tunnel.

    Essentially, the mechanism I’ve been using for instantiating the SessionFactory is not compatible with IoC, whether I was using WCF or not.

    Your approach is much neater.

  6. Davy Brion Says:

    one thing you have to keep in mind if you do it through the attribute is that you won’t have an easy way to reference the current IUnitOfWork instance, and thus, no easy way to ask it to begin a transaction. So the attribute might not be such a good idea, unless you also provide a [Transactional] attribute but then you have to get the attributes to work together properly which might be a bit tricky.

    I was considering going for an attribute based approach as well, but i think i’ll keep the unitofwork/transactional stuff explicitly in the code.

  7. Johnny Hall Says:

    I currently have a [UnitOfWorkContext] (automatic transaction) and a [ReadOnlyUnitOfWorkContext] attribute. I stick the UnitOfWorkContext into the OperationContext, so that I have access to the session and transaction from the operation.

    I’ll have a play with it, see how both approaches feel.

  8. Frederik Gheysels Says:

    Hi,
    I have some questions regarding your solution / implementation.
    - This solution seems to be very usefull in an ASP.NET or Remote Service (WCF, whatever) scenario. However, how do you cope with Rich client applications (Winforms), in where you use NHibernate ? In such a scenario, it is likely to me that you can have multiple sessions opened at a time. (For instance, making use of ‘Long Sessions’. Every form that is opened in your application could have its own Session. How do you cope with that ? Can your ActiveSessionManager cope with that ? It seems that you can have only one session active / open at a time ?

    - How do you do the integration with WCF ? I mean, I do understand that your remote service is the only one that knows about NHibernate. The client of your service should indeed be completely ignorant about NHibernate.
    But, do you use DTO’s that you sent to your client, or, do you share your business objects that you use in the server with your client as well ? In other words: do you transfer your business objects back and forth from the server to the client and vice versa ?
    Or, how does your client knows whether an object has changed , so that you know you have to perform a remote call ? (Or, how does it knows that your object hasn’t changed, so that a remote call is avoided ?).
    Also, how do you attach your objects back to your NHibernate session once you’ve transmitted them to your WCF service, making sure that no unnecessary UPDATES are executed ?

  9. Davy Brion Says:

    The ActiveSessionManager is limited to one active session per thread, so no, it’s not very well suited for WinForms development.

    as for WCF… i prefer the DTO approach because your client really shouldn’t know about your real entities IMHO. If you try to send your entities accross the service wire then you’re opening up a can of worms which actually makes a lot of things a lot more difficult than they should be.

    If you do want to send your entities to the client, then you’ll have to implement your own dirty-tracking within the entities if you want to avoid unnecessary update statements later on when you get back server-side. You’ll also have to use an interceptor (or maybe an event listener in NH2.0) to hook into NHibernate’s dirty checking so you can perform your own custom dirty checks.

    Re-attaching of your entities to the serverside session can be done with session.Update(myEntity) if i recall correctly. This entire scenario is generally discouraged though.

    Mapping from entities to DTO’s and back again seems like it’s a lot of work, but it’s easy code and it actually avoids a lot of complexity later on :)

    And about avoiding the remote calls if the object hasn’t changed… regardless of whether you’re using entities or DTO’s, you always know which actions the user has (or hasn’t) performed so it’s usually better to use that to decide whether or not to make a remote call instead of depending on a myEntity.IsDirty check or something like that.

  10. Frederik Gheysels Says:

    That’s where I wanted to go :) : if you send your business objects to the client, you indeed have to implement your own dirty checking, which is a pity since NHibernate is already taking care of that.

    So, indeed, I agree with you that it using DTO’s is maybe the preferred approach, although it initially adds another layer of complexity, and tedious code.

    Another thing that I’m thinking off: I can image that you would want some simple logic (validation-logic maybe) to be available at the client as well, so your DTO’s should be more then just simple DTO’s but, you wouldn’t want to duplicate any code as well.

  11. Hüseyin Tüfekçilerli Says:

    Great example! I am in the middle of a project which uses NHibernate with WCF and I will probably make use of this pattern/solution in my project.

    A small note: In DisposeObjects() method of your UnitOfWork class, you don’t need to call both Close() and Dispose() methods on session object, they both do the same thing. Actually there is no harm in this case, because the second call will simply be ignored. The classes that use Disposable pattern generally expose methods like Close() to do the same thing with Dispose(), probably “Close” word is counter to the “Open” which had initialized that object.

  12. matizha.com » Gestion des sessions NHibernate Says:

    [...] Il existe plusieurs stratégies pour gérer ce problème avec ASP.Net. Dave Byron propose une solution assez simple via un pattern de Unit of Work. Toutefois, cette méthode nécessite également des connaissances [...]

  13. dario-g Says:

    Hi,
    At first minute I think great example of code but now I must refactor my DAL :/

    Using ThreadStaticAttribute within ASP.NET is not good option. More on that “these should NEVER be used from ASP.NET” !!! Read more here: http://www.hanselman.com/blog/StoringThingsOnThreads.aspx. ASP.NET uses ThreadPool which reuses threads. So, same session can be used in different thread…

  14. Davy Brion Says:

    If you initialize a new session for every request (as you should), then the current thread (the one handling the request) will _always_ have a new session, and never one from a previous thread. That works for regular ASP.NET, as well as for the threads that are handling WCF service calls (in whatever hosting option you choose)

  15. Davy Brion Says:

    hmm… about the whole ThreadStatic thing, i kinda changed my mind on it :)

    more info here: http://davybrion.com/blog/2009/01/abstracting-request-state/

  16. Chuck Says:

    Davy –

    Thanks! This is really putting together some pieces that I was missing while working with NHibernate. Just a quick question, I could not find on your site the implementation of Disposable that calls the ClearReferences() method. At what point in Disposable does that get called?

    Chuck

  17. Davy Brion Says:

    yeah sorry about that, one of the very first versions of the Disposable class had the ClearReferences method. I’ve since updated the original post… the Disposable class now looks like this:

    http://davybrion.com/blog/2008/06/disposing-of-the-idisposable-implementation/

    The ClearReferences method as used in this post has been replaced by the DisposeUnmanagedResources method, though they don’t have the same purpose. The ClearReferences method was basically a mistake :)

    Umm, but to make a long answer short: it was also called in Dispose :)

  18. Chuck Says:

    Davy –

    I was just coming on to post that I had found your source code on the site. Again, between you and Steve B. I have learned sooo much about NHibernate.

    Cheers.

    C

  19. Davy Brion Says:

    thanks :)

  20. Chuck Says:

    Davy –

    I was trying to write a small Web App to try and put all of these pieces together. I have also implemented the ActiveSessionManager to use the IRequestState which I would pass in AspNetRequestState in the Constructor.

    So here is where I am getting lost.

    I am assuming that the “GetAllProductCategories” method (last bit of code in the post) would be in a seperate assembly from the web application.

    If the IOC Container is Resolving the UnitOfWork, but, it is not in the web application, how will the AspNetRequestState be able to pull the Nhibernate Session out of HTTPContext?

    Thanks

    Chuck

  21. Davy Brion Says:

    i’m not sure if i understand what exactly it is that you’re asking but i’ll give it a shot anyways:

    every class that needs request-scoped state would talk to something that implements IRequestState, but they would never know the specific type of the actual implementation. So, if you have another assembly which contains only your businesslayer (and no reference to System.Web), then you should have classes which need request-state depend on an IRequestState instance.

    At runtime, the container will inject AspNetRequestState into each class which has a dependency on IRequestState, but none of those classes will even know that they are talking with AspNetRequestState. Since the business assembly is running within the ASP.NET context, your AspNetRequestState can do anything it wants with the current HttpContext. Or, if the business assembly is running in a different context (in a WCF service for instance) then the container would be configured to inject WcfRequestState. None of the classes that need request-state would know anything about either AspNetRequestState or WcfRequestState though… they just know IRequestState

    Hope that answers your question :)

  22. Chuck Says:

    Davy –

    Thanks! I think that is steering me in the right direction. I am trying to learn how to apply several patterns (IOC, DI, etc) all at once while learning a new ORM AND trying to do it all in the web. This learning seems steep.

    C

  23. Kris-I Says:

    Hello,

    You don’t have a full example of this ? Thanks

  24. Davy Brion Says:

    Not one that i can just give out right now, sorry

  25. Trevor Westerdahl Says:

    Arg! No example?

    I would love to see one simple example… how does one persuade you?

  26. Ian Mckay Says:

    Hi,

    A quick question regarding your implementation of the service layer. Doesn’t the explicit call to IoC container, Container.Resolve()
    limit your testability. It would seem to make sense to pass in the UoW on the constructor.

    How do you test this?

    I like the use of the using statement however the only disadvantage I could see is if you wanted to chain service method calls. With each method call the UoW would dispose of the Session.

    Thanks,

  27. Davy Brion Says:

    @Ian

    that service layer implementation is just some example code… in my real service layer, the IUnitOfWork instance is indeed injected instead of resolved manually

  28. Ian Mckay Says:

    Hi,

    I have found this article extremely useful. I just thought I’d share one minor change I made. When injecting the IUnitOfWork from my controller, the session was being started even if my action was not using the database (because the constructor was being fired). It was then throwing an error on the next action to use the UoW because the previous session hadn’t been disposed. I added an extra method to the IUnitOfWork:

    public interface IUnitOfWork : IDisposable
    {
    ..
    ///
    /// Starts the Unit of Work
    ///
    /// Itself
    IUnitOfWork Start();
    }

    And moved the setActiveSession logic out of the constructor and into this method. Because it returns itself it can still be used in the using block.

    using (unitOfWork.Start())(

    Again, many thanks for the article. Keep up the good work. :)

  29. lemycanh Says:

    I had google and google… nhibernate session management for winform, finaly, i found your article, this’s a great article, thanks alot!
    (sorry for my poor english :D )

  30. Morten Jacobsen Says:

    Great post.. I am learning a lot about keeping code loosely coupled.. I have a question though.. How would you do it if you had to insert or update the values instead of reading them? Would you do something akin to the following?

    public void InsertCategory(ProductCategoryDTO dto)
    {
    using(var uow = Container.Resolve())
    {
    using (ITransaction transaction = uow.CreateTransaction())
    {
    try
    {
    var pc = CreateProductCategoryFromDto(dto);
    var repository = Container.Resolve();
    repository.SaveOrUpdate(pc);
    transaction.Commit();
    }
    catch(SomeException e)
    {
    transaction.Rollback();
    }
    }
    }
    }

    Or do you have a better/more elegant way?

    Thanks in advance,
    Morten Jacobsen

  31. Davy Brion Says:

    I almost never resolve components manually

    Agatha resolves the request handler for the current request, and that request handler simply declares all the dependencies that it needs to handle the request. Agatha automatically releases the resolved request handler, and the request handler disposes of its dependencies

  32. kurt schroeder Says:

    I have to say thanks, not just for this article, but for all the others. I noticed a request for an example just curious if you ever got around to one. I’m still a bit new to NHibernate and DI, IoC, .. I get unsure of what should go where. These articles have helped a lot.

  33. Davy Brion Says:

    @kurt

    what kind of example do you want?

  34. kurt schroeder Says:

    yes i suppose that would help to know that. You’d figure i’d realize specifics are a bit important having worked a tech line at one point. Your patience on that one is appreciated.
    Bear in mind that i’m new to NH and may make some obvious mistakes. I can manage session, drawing upon a friends advise, in command objects by just ending the session with close. I’m making all execute methods return an IResponse to be cast as the correct type. In this case a void would work, but for consistancy it will return an EmptyResponse(). In the case of a Collection, List, … IResponse would be implimented a List, collection, … I did not come up with that idea and don’t want to take credit for thinking of it.

    public IResponse Execute()
    {
    var sessionProvider = IoC.Container.Resolve();
    var junkRepository = IoC.Container.Resolve();
    sessionProvider.StartSession();
    junkRepository.Save(junk);
    sessionProvider.EndSession();
    return new EmptyResponse();
    }

    In the repositories I’m hoping that i can do something similar.

    public IEnumerable GetJunk()
    {
    var sessionProvider = IoC.Container.Resolve();
    var queryString = “select j from Junk j”;
    var query = sessionProvider.GetCurrentSession().CreateQuery(queryString);
    query.SetResultTransformer(new DistinctRootEntityResultTransformer());
    return query.List();
    }

    The obvious problem i’m having when i do this is the session not being handled correctly. Am I off base by using this at all in the repository and should just stick with command objects?
    I’m guessing this is where the UnitofWork could come in, but i’m a little fuzzy on how to do this.

    I’m up for an example because i have a lot of questions like this and others.

  35. Davy Brion Says:

    @Kurt

    you’re resolving your dependencies manually instead of having them injected… looking back on this post, i did the same thing in the example which i would no longer recommend

    i’ll write a new post with an example that hopefully makes this clear… it’ll be based on the NhRequestHandler that you’ve already seen in another post though ;)

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>