views:

50

answers:

2

I have a WCF Service, hosted inside of IIS, using NHibernate for data access.

In my Global.asax I configure NHibernate on Application_Start. This means that I only perform the expensive task of setting up all of the mappings once for my WCF Service.

The only problem with this is that if the database was unavailable during start up, the mappings will never get set up (as they will have failed to be set up during Application_Start and the event won't be called again until the app pool is recycled).

How can I handle the NHibernate set up so it occurs only once, except where there is an error (such as the database not being available) in which case it will occur on each request until it works?

A: 

What you need is a Lazy Singleton to be your SessionFactory. You call a method to get the session factory and it checks if the session already exists. So the expensive task of creating the Session Factory is done the first time someone needs it.

You could do something like this:

public ISessionFactory GetSessionFactory()
    {
        // sessionFactory is STATIC
        if (sessionFactory == null)
        {

            global::NHibernate.Cfg.Configuration cfg = new NHibernateConfigurationFactory(CurrentConfiguration).GetConfiguration(sessionFactoryName);

            //  Now that we have our Configuration object, create a new SessionFactory
            sessionFactory = cfg.BuildSessionFactory();

            if (sessionFactory == null)
            {
                throw new InvalidOperationException("cfg.BuildSessionFactory() returned null.");
            }
        }

        return sessionFactory;
    }

A complete solution is available here:

http://stackoverflow.com/questions/310691/nhibernate-good-complete-working-helper-class-for-managing-sessionfactory-sessi

Pedro
One thing you have to be careful of with a lazy singleton is that you can hit threading issues while the lazy singleton is being constructed as it is possible for concurrent requests to race the construction and attempt to use the non null, but also not fully registered, session.
Sohnee
A: 

I am throwing this answer into the mix in order to get comments on it - this answer was emailed to me, but I'd appreciate the view of the SO community before I decide on the final solution...

Rather than using the Application_Start event, use the Begin_Request event. Store the NHibernate session in a field and in the Begin_Request event, check if the field is null and if it is, create the NHibernate session (otherwise, continue to use the one already created).

So essentially, this would mean moving the create logic into a method I can call from Begin_Request in the event of "detecting that the session hasn't yet been created".

Sohnee
you should start a bounty
Pedro
Okay, found a similar solution to this on Ayende Rahien's blog and have decided to go with it. I've used the template design pattern to make it reusable, so from Application_BeginRequest I'm just calling the bass class and passing in a delegate for the custom bits. Seems like a nice solution.
Sohnee
Link to Ayende's blog: http://ayende.com/Blog/archive/2009/08/05/do-you-need-a-framework.aspx
Sohnee