【问题标题】:Opening multiple sessions simultaneously in NHibernate在 NHibernate 中同时打开多个会话
【发布时间】:2009-10-22 20:44:41
【问题描述】:

我终于弄清楚我的代码出了什么问题,但我不确定如何修复它。我有一些后台进程在执行一些数据库维护任务的单独线程上运行。这是正在发生的事情的一个例子:

//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
    }
}

假设我首先开始LongRunningTask。当它运行时,我在另一个线程上启动ShortRunningTaskShortRunningTask 完成并关闭其会话。一旦LongRunningTask 完成,它会尝试对它创建的会话做一些事情,但会抛出一个错误,表明会话已经关闭。

很明显,发生的事情是 ISessionFactory.OpenSession() 不尊重我已经打开 2 个单独会话的事实。关闭ShortRunningTask 中打开的会话也会关闭LongRunningTask 中的会话我该如何解决这个问题?请帮忙!

谢谢!


更新

所以显然每个人都认为我的修复是完全错误的。所以这是我正在使用的配置:

_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();

我没有在 xml 文件中进行配置。应该有吗?我错过了什么。以下是打开多个会话如何失败的另一个示例:

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

【问题讨论】:

  • 您是否为其他线程创建了另一个ISessionFactory
  • 不,我没有。这是我需要做的吗?
  • 会话工厂是完全线程安全的。请发布更多代码、错误、堆栈跟踪等。
  • 看起来一些 SessionContext 是就地的。 Session Factory 是如何设置的?
  • What goes in "//在这里做一些其他的操作。" ?你能构建一个运行的、独立的测试用例吗?

标签: multithreading nhibernate


【解决方案1】:

我想出了如何解决这个问题。我将我的 SessionFactory 设置为单例,使其成为 [ThreadStatic],如下所示:

[ThreadStatic]
private ISessionFactory _sessionFactory;

[ThreadStatic]
private bool _isInitialized;

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

问题的症结在于,在来自同一个 ISessionFactory 的不同线程上创建会话是有问题的。 ISessionFactory 不喜欢同时打开多个 ISession。关闭一个,自动关闭任何其他打开的。使用[ThreadStatic] 属性为每个线程创建一个单独的ISessionFactory。这使我可以在每个线程上打开和关闭 ISession,而不会影响其他线程。

【讨论】:

  • 您通过引入更多问题解决了一个问题。例如,二级缓存将被破坏。默认情况下,每次调用 OpenSession() 都会为您提供不同的会话实例。请仔细检查您的会话工厂配置。
  • 我同意广州。坏主意。
  • 检查我的会话工厂配置。我应该检查什么?我正在使用流利的 NHibernate。它应该是什么样子?
猜你喜欢
  • 1970-01-01
  • 2011-01-14
  • 2011-12-12
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-28
相关资源
最近更新 更多