c# - Asegúrese de que NHibernate SessionFactory solo se cree una vez
mapping fluent nhibernate (2)
El sessionFactory
debe ser un singleton seguro para subprocesos.
Un patrón común en Java es construir el sessionFactory
en un inicializador estático. Ver HibernateUtil . Puedes hacer lo mismo en C #.
Existen otros patrones para implementar singleton, incluido el uso de bloqueo o secciones sincronizadas. Aquí hay una pequeña variante que debería resolver su problema si lo entendí correctamente.
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();
}
He escrito una clase NHibernateSessionFactory que contiene un Nhibernate ISessionFactory estático. Esto se utiliza para asegurarnos de que solo tenemos una fábrica de sesiones, y la primera vez que se llama OpenSession () creo la SessionFactory actual - las próximas veces que use el mismo y abra una sesión en él. El código se ve así:
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);
}
}
Ahora tengo un problema Mi aplicación se divide entre cliente y servidor. El material de Nhibernate está en el lado del servidor. Al inicio, tanto mi cliente como mi servidor desean acceder a la base de datos a través de algunos servicios que utilizarán NhibernateSessionFactory. El resultado es una condición de carrera para si se crea _sessionFactory antes de que la solicitud provenga del cliente. Si no es así, fallará ...
Supongo que necesito algún tipo de mecanismo de cola o espera en la NhibernateSessionFactory, pero no estoy seguro de qué hacer. ¿Alguien tuvo el mismo problema antes? ¿Cuál es la mejor solución?
Lo resolví usando un Mutex al crear el SessionFactory. ¿Esto se ve razonable?
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);
}
}
Parece funcionar como un encanto. Pero, ¿debería usar el bloqueo en su lugar?