C# 确保 NHibernate SessionFactory 只创建一次
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2362195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Ensure NHibernate SessionFactory is only created once
提问by stiank81
I have written an NHibernateSessionFactory class which holds a static Nhibernate ISessionFactory. This is used to make sure we only have one session factory, and the first time OpenSession() is called I create the actuall SessionFactory - next times I use the same and open a session on it. The code looks like this:
我编写了一个 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);
}
}
Now I have a problem. My application is split between client and server. The Nhibernate stuff is on the server side. On startup both my client and server wants to access the database through some services which will use the NhibernateSessionFactory. Result is a race condition to whether the _sessionFactory is created before the request comes from the client. If it isn't it will fail..
现在我有一个问题。我的应用程序在客户端和服务器之间拆分。Nhibernate 的东西在服务器端。在启动时,我的客户端和服务器都希望通过一些将使用 NhibernateSessionFactory 的服务访问数据库。结果是 _sessionFactory 是否在请求来自客户端之前创建的竞争条件。如果不是它会失败..
I guess I need some sort of queueing or wait mechanism in the NhibernateSessionFactory, but I'm not sure about what to do. Anyone had the same problem before? What's the best solution?
我想我需要在 NhibernateSessionFactory 中使用某种排队或等待机制,但我不确定该怎么做。以前有人遇到过同样的问题吗?最好的解决办法是什么?
采纳答案by ewernli
The sessionFactory
must be a thread-safe singleton.
本sessionFactory
必须是线程安全的单。
A common pattern in Java is to build the sessionFactory
in a static initializer. See HibernateUtil. You can do the same in C#.
Java 中的一个常见模式是sessionFactory
在静态初始化程序中构建。请参阅HibernateUtil。你可以在 C# 中做同样的事情。
There are other patternsto implement singleton, including the usage of lock or synchronized sections. Here is slight variant that should solve your problem if I understood it correctly.
还有其他模式可以实现单例,包括使用锁或同步部分。如果我理解正确,这里有轻微的变体应该可以解决您的问题。
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();
}
回答by stiank81
I solved this using a Mutexwhen creating the SessionFactory. Does this look reasonable:
我在创建 SessionFactory 时使用互斥体解决了这个问题。这看起来合理吗:
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);
}
}
Seems to work like a charm. But should I use lock instead?
似乎很有魅力。但是我应该用锁代替吗?