【问题标题】:NHibernate session per request implementation每个请求实现的 NHibernate 会话
【发布时间】:2011-10-12 11:25:35
【问题描述】:

我想用每个请求实现的会话来重建多线程 NHibernate 应用程序。

现在这个应用程序看起来像每个会话(每个线程)的会话,并将会话保存到 CurrentSessionContext 中。

但是这种实现带来了加载缓存实体的问题,这些实体可能已经从其他会话中更新。所以我想改变这段代码

//main thread 
using (nHibernateHelper.OpenConnection()){
    List<Bar> bars = BarRepository.Instance.GetAll();
    foreach (Bar bar in bars){
        //start thread and do some work, for example run DoWork(bar); by other thread
        Task.Factory.StartNew(DoWork, bar);
    }
}

//other thread
void DoWork(Bar bar){
    using (nHibernateHelper.OpenConnection()){
        foreach (Foo foo in bar.FooList){
            if (foo.SomeState == PredifinedState) {
                //call many other functions
            }
        }
    }
}

主要问题是:如何更改此代码,在使用 LazyLoading 启动其他线程之前关闭 Session(Bar 包含与其他对象的关系,并且在线程工作期间使用此关系),以及在从 foreach 语句调用其他函数之前DoWork 函数?

【问题讨论】:

  • 我使用 ThreadStaticSessionContext 上下文会话,并且 nHibernateHelper.OpenConnection() 是 IDisposable 从 CurrentSessionContext 返回此会话(或使用绑定/取消绑定创建新的)。

标签: nhibernate session lazy-loading


【解决方案1】:

在 NHibernate 中,会话显然不是线程安全的(请参阅http://nhibernate.info/doc/nh/en/index.html#transactions),因此您不能在没有锁定的情况下在多个线程之间共享它们。

如果没有更多关于您的问题的背景信息,很难提供一个准确的解决方案,但是下面的内容会有所帮助吗?

//main thread 

    List<Bar> bars = BarRepository.Instance.GetAll();
    foreach (Bar bar in bars){
        //start thread and do some work, for example run DoWork(bar); by other thread
        Task.Factory.StartNew(DoWork, bar, NHibernateHelper.CurrentSession());
    }

void DoWork(Bar bar, ISession session){
    foreach (Foo foo in bar.FooList){
        if (foo.SomeState == PredifinedState) {
            //call many other functions
            lock (session)
            {
                using (var tran = session.BeginTransaction())
                {
                    session.Save(foo);
                    tran.Commit();
                }                
        }
    }
}

【讨论】:

  • Task.Factory.StartNew(DoWork, bar, NHibernateHelper.CurrentSession());。您的数据库服务器将开始发射放射性物质。然而,从技术上讲,这是对这个问题的正确答案。
  • 对不起,我指定了,我使用 ThreadStaticSessionContext contextual sessions ,所以我们不需要将 Session 对象传递给其他线程。主要思想是将每个应用程序管理策略的会话(现在看起来像这样)更改为每个工作单元的会话。我知道如何通过 IDisposable 类和将上下文会话更改为 CallSessionContext 来实现这一点。但是:我需要用长的 foreach 周期做什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-19
  • 2012-10-23
  • 2012-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多