确保NHibernate SessionFactory仅创建一次

我编写了一个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()); _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中使用某种排队或等待机制,但我不知道该怎么做。 以前有人有同样的问题吗? 什么是最好的解决方案?

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

Java中的一个常见模式是在静态初始化程序中构建sessionFactory 。 请参阅HibernateUtil 。 您可以在C#中执行相同的操作。

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

 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()); _sessionFactory = cfg.BuildSessionFactory(); BuildSchema(cfg); } } return _sessionFactory.OpenSession(); } 

我在创建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()); _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); } } 

似乎像魅力一样工作。 但我应该使用锁吗?