redes - NHibernate-buena clase completa de trabajo de ayuda para administrar SessionFactory/Session
hootsuite no es gratis (9)
¿Alguien puede proporcionar / referir una clase de ayuda de tipo OO adecuada para administrar un singleton de SessionFactory y luego también para gestionar Sessions?
¡Gracias! Esto es útil, pero estoy buscando algo que sea un poco más robusto.
Por ejemplo, se hace referencia en el sitio NH ( http://hibernate.org/363.html#A9 ) es una contribución hecha por Andrew Mayorov y publica tres archivos como este ( http://nhibernate.sourceforge.net/contrib /Wiki_AndrewMayorovAspNet.zip ).
La cosa es que no viene con mucha ayuda. No estoy exactamente seguro de cómo usarlo correctamente. Intenté algunas cosas, pero tuve problemas.
Alguien tiene algo que usa esto o similar?
Claro, esto es lo que usé cuando empecé con NHibernate:
Fábrica de sesión
public class BaseDataAccess
{
protected ISession m_session;
public BaseDataAccess()
{
m_session=NHibernateHttpModule.CurrentSession;
}
public static ISession OpenSession()
{
Configuration config;
ISessionFactory factory;
ISession session;
config = new Configuration();
if (config==null)
{
throw new InvalidOperationException("NHibernate configuration is null.");
}
config.AddAssembly("My.Assembly.Here");
factory = config.BuildSessionFactory();
if (factory==null)
{
throw new InvalidOperationException("Call to Configuration.BuildSessionFactory() returned null.");
}
session = factory.OpenSession();
if (session==null)
{
throw new InvalidOperationException("Call to factory.OpenSession() returned null.");
}
return session;
}
}
Avísame si eso ayuda.
He tenido un gran éxito en el pasado usando los módulos de soporte NHibernate de Spring.NET. Ver http://www.springframework.net/downloads/Spring.Data.NHibernate/ . Debería poder usar el módulo OpenSessionInView y extender sus DAO fuera del NHibernateSupport DAO para obtener soporte completo de administración de la sesión abierta en el patrón de vista .
Además, aunque nunca lo intenté, debería poder utilizar el marco mencionado anteriormente incluso si opta por no restablecer las ofertas de Spring.NET (concretamente IoC y AOP).
Recomiendo ver la biblioteca de Rhino Commons de Ayende . La documentación es un poco escasa en este momento, pero una vez que esté en funcionamiento, trabajar con NHibernate será MUCHO más fácil.
Escribí una publicación de blog sobre esto en la que uso la implementación web administrada del manejo de sesión contextual. Tal vez eso es lo que estás buscando?
NHibernate Burrow parece prometedor. Empecé a usarlo y no tengo problemas hasta la fecha.
Dos sugerencias:
- Jeffrey Palermo''s HybridSessionBuilder (jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple)
- Vea los ejemplos del código (específicamente vea la sesión 13) en el verano de NHibernate (www.summerofnhibernate.com)
Es posible que desee considerar que su DAL esté menos relacionado con la gestión de las sesiones de NHibernate aprovechando NHibernate.Burrow (o implementando un patrón similar por su cuenta).
"NHibernate.Burrow es un middleware liviano desarrollado para admitir aplicaciones .Net que utilizan NHibernate al proporcionar una gestión de sesión / transacción inteligente y avanzada y otras funciones más fáciles".
Si decides enrollar el tuyo, hay algunos enlaces útiles al pie de esta página:
Un término de búsqueda de Google útil sería ''NHibernate Session Management'' y ''Contextual Sessions'' ...
No hay escasez de ideas; podría decirse que hay demasiadas opciones, ojalá la opinión comience a gravitar alrededor de Burrow o algo así ...
Mira el trabajo de Billy McCafferty . Su versión anterior tenía algunas limitaciones, necesitarás corregir el manejo del error al cerrar y enrojar, y no estoy seguro de que esté bien, pero publicaré cómo modifiqué sus cosas.
Billy también está trabajando en un nuevo marco que usa MVC & nHibernate llamado S #arp Architechure que estoy usando actualmente, y hasta ahora todo va bien.
De todos modos aquí está mi versión modificada de su código. No hago guantas sobre la precisión o la completitud y lo está utilizando bajo su propio riesgo. Si usa esto, asegúrese de cerrar la sesión. Si tienes alguna pregunta, envíame un correo electrónico [joshua] [dot] [berke] a [gmail ... ya sabes el resto].
/// <summary>
/// Handles creation and management of sessions and transactions. It is a singleton because
/// building the initial session factory is very expensive. Inspiration for this class came
/// from Chapter 8 of Hibernate in Action by Bauer and King. Although it is a sealed singleton
/// you can use TypeMock (http://www.typemock.com) for more flexible testing.
/// </summary>
public sealed class NHibernateSessionManager
{
private const string DefaultConfigFile = "DefaultAppWeb.Config";
private static readonly object _syncRoot = new object();
#region Thread-safe, lazy Singleton
/// <summary>
/// This is a thread-safe, lazy singleton. See http://www.yoda.arachsys.com/csharp/singleton.html
/// for more details about its implementation.
/// </summary>
public static NHibernateSessionManager Instance
{
get
{
return Nested.NHibernateSessionManager;
}
}
/// <summary>
/// Private constructor to enforce singleton
/// </summary>
private NHibernateSessionManager() { }
/// <summary>
/// Assists with ensuring thread-safe, lazy singleton
/// </summary>
private class Nested
{
static Nested() { }
internal static readonly NHibernateSessionManager NHibernateSessionManager =
new NHibernateSessionManager();
}
#endregion
/// <summary>
/// This method attempts to find a session factory stored in <see cref="sessionFactories" />
/// via its name; if it can''t be found it creates a new one and adds it the hashtable.
/// </summary>
/// <param name="sessionFactoryConfigPath">Path location of the factory config</param>
private ISessionFactory GetSessionFactoryFor(string sessionFactoryConfigPath)
{
Check.Require(!string.IsNullOrEmpty(sessionFactoryConfigPath),
"sessionFactoryConfigPath may not be null nor empty");
// Attempt to retrieve a stored SessionFactory from the hashtable.
ISessionFactory sessionFactory;// = (ISessionFactory)sessionFactories[sessionFactoryConfigPath];
// try and get a session factory if we don''t find one create it
lock (_syncRoot)
{
if (!sessionFactories.TryGetValue(sessionFactoryConfigPath, out sessionFactory))
{
Configuration cfg = new Configuration();
if (sessionFactoryConfigPath != DefaultConfigFile)
{
Check.Require(File.Exists(sessionFactoryConfigPath),
"The config file at ''" + sessionFactoryConfigPath + "'' could not be found");
cfg.Configure(sessionFactoryConfigPath);
}
else
{
cfg.Configure();
}
// Now that we have our Configuration object, create a new SessionFactory
sessionFactory = cfg.BuildSessionFactory();
Check.Ensure(sessionFactory != null, "sessionFactory is null and was not built");
sessionFactories.Add(sessionFactoryConfigPath, sessionFactory);
}
}
return sessionFactory;
}
/// <summary>
/// Allows you to register an interceptor on a new session. This may not be called if there is already
/// an open session attached to the HttpContext. If you have an interceptor to be used, modify
/// the HttpModule to call this before calling BeginTransaction().
/// </summary>
public void RegisterInterceptorOn(string sessionFactoryConfigPath, IInterceptor interceptor)
{
ISession session = (ISession)ContextSessions[sessionFactoryConfigPath];
if (session != null && session.IsOpen)
{
throw new CacheException("You cannot register an interceptor once a session has already been opened");
}
GetSessionFrom(sessionFactoryConfigPath, interceptor);
}
public ISession GetSessionFrom(string sessionFactoryConfigPath)
{
return GetSessionFrom(sessionFactoryConfigPath, null);
}
/// <summary>
/// Gets or creates an ISession using the web / app config file.
/// </summary>
/// <returns></returns>
public ISession GetSessionFrom()
{
return GetSessionFrom(DefaultConfigFile, null);
}
/// <summary>
/// Gets a session with or without an interceptor. This method is not called directly; instead,
/// it gets invoked from other public methods.
/// </summary>
private ISession GetSessionFrom(string sessionFactoryConfigPath, IInterceptor interceptor)
{
var allSessions = ContextSessions;
ISession session = null;
if (!allSessions.TryGetValue(sessionFactoryConfigPath, out session))
{
if (interceptor != null)
{
session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession(interceptor);
}
else
{
session = GetSessionFactoryFor(sessionFactoryConfigPath).OpenSession();
}
allSessions[sessionFactoryConfigPath] = session;
}
//session.FlushMode = FlushMode.Always;
Check.Ensure(session != null, "session was null");
return session;
}
/// <summary>
/// Flushes anything left in the session and closes the connection.
/// </summary>
public void CloseSessionOn(string sessionFactoryConfigPath)
{
ISession session;
if (ContextSessions.TryGetValue(sessionFactoryConfigPath, out session))
{
if (session.IsOpen)
{
session.Flush();
session.Close();
}
ContextSessions.Remove(sessionFactoryConfigPath);
}
}
public ITransaction BeginTransactionOn(string sessionFactoryConfigPath)
{
ITransaction transaction;
if (!ContextTransactions.TryGetValue(sessionFactoryConfigPath, out transaction))
{
transaction = GetSessionFrom(sessionFactoryConfigPath).BeginTransaction();
ContextTransactions.Add(sessionFactoryConfigPath, transaction);
}
return transaction;
}
public void CommitTransactionOn(string sessionFactoryConfigPath)
{
try
{
if (HasOpenTransactionOn(sessionFactoryConfigPath))
{
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
transaction.Commit();
ContextTransactions.Remove(sessionFactoryConfigPath);
}
}
catch (HibernateException he)
{
try
{
RollbackTransactionOn(sessionFactoryConfigPath);
}
finally
{
throw he;
}
}
}
public bool HasOpenTransactionOn(string sessionFactoryConfigPath)
{
ITransaction transaction;
if (ContextTransactions.TryGetValue(sessionFactoryConfigPath, out transaction))
{
return !transaction.WasCommitted && !transaction.WasRolledBack;
}
return false;
}
public void RollbackTransactionOn(string sessionFactoryConfigPath)
{
try
{
if (HasOpenTransactionOn(sessionFactoryConfigPath))
{
ITransaction transaction = (ITransaction)ContextTransactions[sessionFactoryConfigPath];
transaction.Rollback();
}
ContextTransactions.Remove(sessionFactoryConfigPath);
}
finally
{
ForceCloseSessionOn(sessionFactoryConfigPath);
}
}
/// <summary>
/// Since multiple databases may be in use, there may be one transaction per database
/// persisted at any one time. The easiest way to store them is via a hashtable
/// with the key being tied to session factory. If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Dictionary<string, ITransaction> ContextTransactions
{
get
{
if (IsInWebContext())
{
if (HttpContext.Current.Items[TRANSACTION_KEY] == null)
HttpContext.Current.Items[TRANSACTION_KEY] = new Dictionary<string, ITransaction>();
return (Dictionary<string, ITransaction>)HttpContext.Current.Items[TRANSACTION_KEY];
}
else
{
if (CallContext.GetData(TRANSACTION_KEY) == null)
CallContext.SetData(TRANSACTION_KEY, new Dictionary<string, ITransaction>());
return (Dictionary<string, ITransaction>)CallContext.GetData(TRANSACTION_KEY);
}
}
}
/// <summary>
/// Since multiple databases may be in use, there may be one session per database
/// persisted at any one time. The easiest way to store them is via a hashtable
/// with the key being tied to session factory. If within a web context, this uses
/// <see cref="HttpContext" /> instead of the WinForms specific <see cref="CallContext" />.
/// Discussion concerning this found at http://forum.springframework.net/showthread.php?t=572
/// </summary>
private Dictionary<string, ISession> ContextSessions
{
get
{
if (IsInWebContext())
{
if (HttpContext.Current.Items[SESSION_KEY] == null)
HttpContext.Current.Items[SESSION_KEY] = new Dictionary<string, ISession>();
return (Dictionary<string, ISession>)HttpContext.Current.Items[SESSION_KEY];
}
else
{
if (CallContext.GetData(SESSION_KEY) == null)
CallContext.SetData(SESSION_KEY, new Dictionary<string, ISession>());
return (Dictionary<string, ISession>)CallContext.GetData(SESSION_KEY);
}
}
}
private bool IsInWebContext()
{
return HttpContext.Current != null;
}
private Dictionary<string, ISessionFactory> sessionFactories = new Dictionary<string, ISessionFactory>();
private const string TRANSACTION_KEY = "CONTEXT_TRANSACTIONS";
private const string SESSION_KEY = "CONTEXT_SESSIONS";
public bool HasOpenTransactionOn()
{
return HasOpenTransactionOn(DefaultConfigFile);
}
public void CommitTransactionOn()
{
CommitTransactionOn(DefaultConfigFile);
}
public void CloseSessionOn()
{
CloseSessionOn(DefaultConfigFile);
}
public void ForceCloseSessionOn()
{
ForceCloseSessionOn(DefaultConfigFile);
}
public void ForceCloseSessionOn(string sessionFactoryConfigPath)
{
ISession session;
if (ContextSessions.TryGetValue(sessionFactoryConfigPath, out session))
{
if (session.IsOpen)
{
session.Close();
}
ContextSessions.Remove(sessionFactoryConfigPath);
}
}
public void BeginTransactionOn()
{
this.BeginTransactionOn(DefaultConfigFile);
}
public void RollbackTransactionOn()
{
this.RollbackTransactionOn(DefaultConfigFile);
}
}