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 pl开发者_如何学Pythonace 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!'
}
}
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.
精彩评论