首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Castle.Facilities.NHibernateIntegration ISessionManager在Web上下文中的线程安全问题

Castle.Facilities.NHibernateIntegration ISessionManager在Web上下文中的线程安全问题
EN

Stack Overflow用户
提问于 2011-04-25 20:08:10
回答 3查看 1.3K关注 0票数 0

因此,基于我上周提出的这个问题(here),我决定去看看城堡项目,并使用Castle.Facilities.NHibernateIntegration工具。

我花了两天中的大部分时间来处理这个问题,并讨论了同样的问题: NHibernate线程安全会话。我本来希望,在ISessionManager中内置的内核足够聪明,能够处理线程,这就是我决定实现它的原因。

在关于该特定项目的非常稀疏的文档中,它提到调用ISessionManager.OpenSession与调用session.GetCurrentSession非常相似。由此,我认为没有办法让我,强行打开,一个新的独立的会议。

那么,有没有人为我找到解决办法,或者有什么想法来解决这个问题呢?

(我知道大多数人都会说只使用一个线程,但老实说,有些工具和例程会自动生成一个新线程。例如,log4net和sessionstatestore。您不能仅仅假设只有一个线程,即与当前请求关联的)。

备注:

  • 我正在开发.NET 4 web应用程序的web模型,
  • 以通常的、有文档化的方式调用和解析温莎容器,并让容器解析会话管理器。我在这两个线程中都这样做。
  • ,这里是my城堡NHibernate配置:

代码:

代码语言:javascript
复制
<facility id="nhibernate" isWeb="true" type="Castle.Facilities.NHibernateIntegration.NHibernateFacility, Castle.Facilities.NHibernateIntegration">
  <factory id="nhibernate.factory">
    <settings>
      <item key="connection.connection_string">#{NHibernateConnectionString}</item>
      <item key="connection.driver_class">#{NHibernateDriver}</item>
      <item key="connection.provider">NHibernate.Connection.DriverConnectionProvider</item>
      <item key="dialect">#{NHibernateDialect}</item>
      <item key="generate_statistics">true</item>
      <item key="proxyfactory.factory_class">NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle</item>
      <item key="show_sql">true</item>
    </settings>
    <assemblies>
      <assembly>Gigastence.Base.Common</assembly>
    </assemblies>
  </factory>

  • 这里是我的DAO

示例

代码:

代码语言:javascript
复制
public class NHibernateDao : INHibernateDao
{
    private ISessionManager sessionManager;

    public NHibernateDao(ISessionManager sessionManager)
    {
        this.sessionManager = sessionManager;
    }

    public void Append(LoggingEvent loggingEvent)
    {
        using (IStatelessSession session = sessionManager.OpenStatelessSession())
        {
            using (ITransaction tran = session.BeginTransaction())
            {
                Log data = new Log
                {
                    Id = Guid.NewGuid(),
                    Date = loggingEvent.TimeStamp,
                    Level = loggingEvent.Level.ToString(),
                    Logger = loggingEvent.LoggerName,
                    Thread = loggingEvent.ThreadName,
                    Message = loggingEvent.MessageObject.ToString()
                };

                if (loggingEvent.ExceptionObject != null)
                {
                    data.Exception = loggingEvent.ExceptionObject.ToString();
                }

                session.Insert(data);
                tran.Commit();
            }
        }
    }
}

  • 和我如何调用DAO。注意:,这是在我无法控制的新产生的线程上。

代码:

代码语言:javascript
复制
public class NHibenateAppender : AppenderSkeleton
{
    protected override void Append(LoggingEvent loggingEvent)
    {
        if(IoC.IsInitialized)
        {
            var NHibernateLogger = IoC.Resolve<INHibernateDao>();
            NHibernateLogger.Append(loggingEvent);
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-04-26 08:26:00

如果您希望完全控制会话,我相信NHibernateFacility实际上将底层ISessionFactory注册到温莎内核。

由此,您可以调用sessionFactory.OpenSession(),我认为它应该总是返回一个新会话。

我真的不明白ISessionManager给派对带来了什么.

票数 0
EN

Stack Overflow用户

发布于 2011-05-04 17:52:06

看看这个链接!https://github.com/haf/Castle.Facilities.NHibernate/wiki

它可能解决您的多线程问题,因为它的意图与以前的工具不同;这个工具允许您保留每个事务的会话,而不是每个请求一个会话。因此,避免了多线程问题,并且从您的附录中也可以很好地工作。

在代码中,这是因为.Net有一个CallContext静态类,它知道您在哪个线程上(但是将它绑定到调用上下文而不是线程静态)。

票数 0
EN

Stack Overflow用户

发布于 2013-12-18 16:25:21

在使用SessionPerWebRequest模式时,我们经常遇到这个问题,然后分叉工作线程,正如您所说,在某些情况下,这些线程是无法帮助的。

诀窍就像jishi说的那样;与其从Func<ISession>ISessionManager中提取会话,还需要访问ISessionFactory

不幸的是,这并不像通过构造函数注入它和让温莎解决它那么简单--它没有像jishi所说的那样作为安装程序的一部分注册(除非我遗漏了什么)。但是,可以通过安装程序回调来访问它:

代码语言:javascript
复制
public class NHibernateInstaller : INHibernateInstaller, IDatabaseInstaller
{
    ...

    public void Registered(ISessionFactory factory)
    {
        SessionFactoryStore.Set(SessionFactoryKey, factory);
    }
}

其中,SessionFactoryStore是一个用于存储工厂的单例存储库(在可能有多个工厂的情况下,可以分布在客户端,比如我)。

代码语言:javascript
复制
[Singleton]
public class SessionFactoryStore: ISessionFactoryStore
{
    Dictionary<string, ISessionFactory> SessionFactories { get; set; }

    public SessionFactoryStore()
    {
        SessionFactories = new Dictionary<string, ISessionFactory>();
    }

    public void Set(string key, ISessionFactory factory)
    {
        lock (SessionFactories)
        {
            if (!SessionFactories.ContainsKey(key)) SessionFactories.Add(key, factory);
        }
    }

    public ISessionFactory Get(string key)
    {
        return SessionFactories.ContainsKey(key) ? SessionFactories[key] : null;
    }
}

然后,在实现工作单元模式或类似的地方,只需执行一个测试,看看您是在正常或线程状态下运行:

代码语言:javascript
复制
[PerWebRequest]
public class UnitOfWork : IUnitOfWork
{
    private IGenericFactory GenericFactory { get; set; }

    private Func<ISession> Session { get; set; }
    private ISessionFactoryStore SessionFactoryStore { get; set; }

    private ISession GetSession(bool isThreaded)
    {
        if (!isThreaded)
            return Session();
        else
            return SessionFactoryStore.Get("YourFactoryKey").OpenSession();
    }

    public UnitOfWork(Func<ISession> session, ISessionFactoryStore sessionFactoryStore) {
        Session = session;
        SessionFactoryStore = sessionFactoryStore;
    }

    ...
}

嘿,预告片,线程安全的ISession使用NHibernateIntegration。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5782696

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档