【问题标题】:Ensure NHibernate SessionFactory is only created once确保 NHibernate SessionFactory 只创建一次
【发布时间】:2011-01-22 15:53:22
【问题描述】:

我编写了一个 NHibernateSessionFactory 类,它包含一个静态的 Nhibernate ISessionFactory。这用于确保我们只有一个会话工厂,并且第一次调用 OpenSession() 时,我创建了实际的 SessionFactory - 下次我使用它并在其上打开一个会话。代码如下所示:

public class NhibernateSessionFactory : INhibernateSessionFactory
{
    private static ISessionFactory _sessionFactory;

    public ISession OpenSession()
    {
        if (_sessionFactory == null)
        {
            var cfg = Fluently.Configure().
                Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
            _sessionFactory = cfg.BuildSessionFactory();
            BuildSchema(cfg);
        }
        return _sessionFactory.OpenSession();
    }

    private static void BuildSchema(FluentConfiguration configuration)
    {
        var sessionSource = new SessionSource(configuration);
        var session = sessionSource.CreateSession();
        sessionSource.BuildSchema(session);            
    }
}

现在我有一个问题。我的应用程序在客户端和服务器之间拆分。 Nhibernate 的东西在服务器端。在启动时,我的客户端和服务器都希望通过一些将使用 NhibernateSessionFactory 的服务来访问数据库。结果是在请求来自客户端之前是否创建 _sessionFactory 的竞争条件。如果不是,它将失败..

我想我需要在 NhibernateSessionFactory 中使用某种排队或等待机制,但我不确定该怎么做。以前有人遇到过同样的问题吗?最好的解决方案是什么?

【问题讨论】:

    标签: c# nhibernate fluent-nhibernate sessionfactory


    【解决方案1】:

    sessionFactory 必须是线程安全的单例。

    Java 中的一个常见模式是在静态初始化程序中构建sessionFactory。见HibernateUtil。你可以在 C# 中做同样的事情。

    还有其他patterns 来实现单例,包括使用锁或同步部分。如果我理解正确,这里有一个轻微的变体应该可以解决你的问题。

    static readonly object factorylock = new object();
    
    public ISession OpenSession()
    {
        lock (factorylock)
        {
           if (_sessionFactory == null)
           {
                var cfg = Fluently.Configure().
                   Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                   Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
                _sessionFactory = cfg.BuildSessionFactory();
                BuildSchema(cfg);
            }
        }
        return _sessionFactory.OpenSession();
    }
    

    【讨论】:

    • 谢谢!听起来很合理。我刚刚添加了一个使用 Mutex 的解决方案。但我应该改用 lock 吗?
    • 但是如果我同时需要多个数据库连接怎么办?目前我不知道创建多个会话工厂的其他解决方法......
    • 如何在控制器中实现这一点?
    • 请注意,您的 HibernateUtil 链接现在似乎消失了。
    • 或[MethodImpl(MethodImplOptions.Synchronized)] public static ISession OpenSession()
    【解决方案2】:

    我在创建 SessionFactory 时使用Mutex 解决了这个问题。这看起来合理吗:

    public class NhibernateSessionFactory : INhibernateSessionFactory
    {
        private static ISessionFactory _sessionFactory;
        private static Mutex _mutex = new Mutex();  // <-- Added
    
        public ISession OpenSession()
        {
            if (_sessionFactory == null)
            {
                _mutex.WaitOne();              // <-- Added
                if (_sessionFactory == null)   // <-- Added
                {                              // <-- Added
                    var cfg = Fluently.Configure().
                        Database(SQLiteConfiguration.Standard.ShowSql().UsingFile("Foo.db")).
                        Mappings(m => m.FluentMappings.AddFromAssemblyOf<MappingsPersistenceModel>());
                    _sessionFactory = cfg.BuildSessionFactory();
                    BuildSchema(cfg);
                }                              // <-- Added
                _mutex.ReleaseMutex();         // <-- Added
    
            }
            return _sessionFactory.OpenSession();
        }
    
        private static void BuildSchema(FluentConfiguration configuration)
        {
            var sessionSource = new SessionSource(configuration);
            var session = sessionSource.CreateSession();
            sessionSource.BuildSchema(session);            
        }
    }
    

    看起来像一个魅力。但是我应该改用 lock 吗?

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-04
    • 2013-11-07
    • 2012-07-25
    • 1970-01-01
    • 2012-11-01
    • 2022-11-02
    • 2014-09-13
    • 1970-01-01
    相关资源
    最近更新 更多