4

所以这就是问题所在。我有一个通用类库,其中包含所有存储库、域和映射文件,因此可以在其他基于 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() 方法来获取 ISession。现在这工作正常,但我担心它可能不是线程安全的。任何人都可以帮助我采用一种可以帮助我使其线程安全的方法。

需要注意的几点:

我曾考虑在启动事件时在 web 应用程序的 global.asax 中配置和构建 SessionFactory,但问题是有问题的公共类库在 20 个不同的应用程序中使用,因此这意味着要访问所有应用程序并更新global.asax 文件现在在我这样做之前我想把问题放在那里,看看是否还有其他方法可以解决这个问题。这样通用类库就可以自己配置其 SessionFactory 并且是线程安全的。

感谢您阅读这个巨大的问题。将给予任何帮助。

4

4 回答 4

7

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

    private static object lockObject = new object();

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

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

通过会话工厂创建会话是线程安全的,因此您无需担心。

于 2011-09-09T10:39:32.177 回答
0

我建议为每个请求使用一个会话,如下所示:

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;
}
于 2011-09-09T10:11:39.757 回答
0

NHibernate 中的会话在设计上不是线程安全的。因此,只要您的会话仅由一个线程使用就可以了。只要每个线程都有一个单独的 NHibernate 会话,就可以为多个线程使用一个 NHibernate SessionFactory

有关更多信息,请查看以下链接:

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

于 2011-09-09T10:10:06.370 回答
0

继 Stefan Steinegger 的评论之后,我认为在锁定之前添加一个空检查会更有效,这样如果 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;
        }
    }
}
于 2018-08-21T12:46:30.883 回答