NHibernate SessionFactory线程安全问题

本文关键字:问题 安全 线程 SessionFactory NHibernate | 更新日期: 2023-09-27 18:08:09

问题就在这里。我有一个公共类库,它包含所有的存储库、域和映射文件,因此该库可以在其他基于web的应用程序中重用。现在,在这个类库中有一段代码,它允许自己创建一个会话工厂,以便在其存储库中使用。代码看起来像这样:

        private static ISessionFactory sessionFactory;
        private static Configuration configuration;
        public static Configuration Configuration()
        {
            if (configuration == null)
            {
                configuration = new Configuration().Configure();
            }
            return configuration;
        }
        private static ISessionFactory SessionFactory
        {
            get
            {
                if (sessionFactory == null)
                {
                    sessionFactory = Configuration().BuildSessionFactory();
                }
                return sessionFactory;
            }
        }
        public static ISession GetCurrentSession()
        {
            if (!CurrentSessionContext.HasBind(SessionFactory))
            {
                CurrentSessionContext.Bind(SessionFactory.OpenSession());
            }
            return SessionFactory.GetCurrentSession();
        }

因此存储库调用GetCurrentSession()方法来获取session。现在这工作得很好,但我担心它可能不是线程安全的。谁能告诉我一个方法,使它线程安全?

注意事项:

我考虑过在全局中配置和构建SessionFactory。一个web应用程序的启动事件,但这样做的问题是,有问题的公共类库在20个不同的应用程序中使用,所以这将意味着要去所有的应用程序和更新全局。asax文件现在,在我这样做之前,我想把问题放在那里,看看是否有任何其他的方法,我可以做到这一点。这样,公共类库就可以自己配置它的SessionFactory,并且仍然是线程安全的。

谢谢你阅读这个大问题。将感谢任何帮助。

NHibernate SessionFactory线程安全问题

会话工厂是线程安全的,而会话不是。构建会话工厂需要被保护:

    private static object lockObject = new object();
    private static ISessionFactory SessionFactory
    {
        get
        {
            lock (lockObject)
            {
                if (sessionFactory == null)
                {
                    sessionFactory = Configuration().BuildSessionFactory();
                }
                return sessionFactory;
            }
        }
    }

在线程第一次请求会话时创建会话工厂。这需要是线程安全的,以避免多次创建会话工厂。

通过会话工厂创建会话是线程安全的,所以您不需要担心这个问题。

会话在NHibernate中不是线程安全的。因此,只要您有一个仅由一个线程使用的会话,它应该是可以的。你可以为多个线程使用一个NHibernate SessionFactory,只要你为每个线程使用一个单独的NHibernate会话

更多信息请看下面的链接:

https://forum.hibernate.org/viewtopic.php?p=2373236& sid = db537baa5a57e3968abdda5cceec2a24

我建议为每个请求使用一个会话,像这样:

public ISession GetCurrentSession()
{
        HttpContext context = HttpContext.Current;
        var currentSession = context.Items["session"] as ISession;
        if( currentSession is null )
        {
             currentSession = SessionFactory.GetCurrentSession()
             context.Items["session"] = currentSession;
        }
        return currentSession;
}

根据Stefan Steinegger的评论,我认为在锁定之前立即添加null检查会更有效,这样如果sessionFactory已经初始化,您就不需要每次都锁定。

private static object lockObject = new object();
private static ISessionFactory SessionFactory
{
    get
    {
        if (sessionFactory != null)
        {
            return sessionFactory;
        }
        lock (lockObject)
        {
            if (sessionFactory == null)
            {
                sessionFactory = Configuration().BuildSessionFactory();
            }
            return sessionFactory;
        }
    }
}