views:

153

answers:

1

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!'
    }
}
A: 

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.

Micah
You solved one problem by introducing even more problems. 2nd level cache will be broken for example. By default OpenSession() would give you different session instances each time you invoke it. Please double check your session factory configuration.
Canton
I agree with Canton. Bad, bad idea.
Mauricio Scheffer
Check my session factory configuration. What should I be checking for? I'm using fluent NHibernate. What should it look like?
Micah
Please post more code, errors, stack traces, etc.
Mauricio Scheffer
I updated the question with more details.
Micah