R – Opening multiple sessions simultaneously in NHibernate

multithreadingnhibernate

I finally figured out what's wrong with my code, but I'm not sure how to fix it. I have some background processes running on a separate thread that perform some database maintenance tasks. Here's an exmple of what's happening:

//Both processes share the same instance of ISessionFactory
//but open separate ISessions

//This is running on it's own thread
public void ShortRunningTask()
{
    using(var session = _sessionFactory.OpenSession())
    {
        //Do something quickly here
        session.Update(myrecord);
    }
}

//This is running on another thread
public void LongRunningTask()
{
    using(var session = _sessionFactory.OpenSession())
    {
        //Do something long here
    }
}

Let's say I start LongRunningTask first. While it's running I start ShortRunningTask on another thread. ShortRunningTask finishes up and closes its session. Once LongRunningTask finishes it tries to do something with it's session it created but an error get's thrown saying that the session has already been closed.

Clearly what's happening is that ISessionFactory.OpenSession() is not honoring the fact that I've opened 2 separate sessions. Closing the session opened in ShortRunningTask also closes the session in LongRunningTask How can I fix this? Please help!

Thanks!


UPDATE

So apparently everyone thinks my fix is totally wrong. So here's the configuration I am using:

_sessionFactory = Fluently.Configure()
                  .Database(
                  FluentNHibernate.Cfg.Db.MsSqlConfiguration.MsSql2008
                  .ConnectionString(db => db.Is(
WikipediaMaze.Core.Properties.Settings.Default.WikipediaMazeConnection)))
                  .Mappings(m => m.FluentMappings.AddFromAssemblyOf<IRepository>())
                  .BuildSessionFactory();

I have no configuration taking place in an xml file. Should there be? What am I missing. Here's another example of how opening multiple sessions fails:

public void OpenMultipleSessionsTest()
{
    using(var session1 = _sessionFactory.OpenSession())
    {
        var user = session1.Get<Users>().ById(1);
        user.Name = "New Name";

        using(var session2 = _sessionFactory.OpenSession())
        {
            //Do some other operation here.
        }

        session1.Update(user);
        session1.Flush(); // Throws error 'ISession already closed!'
    }
}

Best Answer

I figured out how to fix the problem. I setup my SessionFactory as a singleton at made it [ThreadStatic] like this:

[ThreadStatic]
private ISessionFactory _sessionFactory;

[ThreadStatic]
private bool _isInitialized;

public ISessionFactory SessionFactory
{
    get
    {
        if(!_isInitialized)
        {
            //Initialize the session factory here
        }
    }
}

The crux of the problem is that creating sessions on separate threads from the same ISessionFactory is problematic. ISessionFactory does not like multiple ISessions being opened at the same time. Closing one, automatically closes any others that are open. Using the [ThreadStatic] attribute creates a separate ISessionFactory for each thread. This allows me to open and close ISessions on each thread without affecting the others.

Related Topic