2008-11-22 4 views

Respuesta

1

Sin duda, esto es lo que usé cuando estaba empezando con NHibernate:

Sesión fábrica

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; 
    } 
} 

Quiero saber si eso ayuda.

0

¡Gracias! Esto es útil, pero estoy buscando algo que sea un poco más robusto.

Por ejemplo, al hacer referencia en el sitio NH (http://hibernate.org/363.html#A9) es una contribución realizada por Andrew Mayorov y publica tres archivos como este (http://nhibernate.sourceforge.net/contrib/Wiki_AndrewMayorovAspNet.zip).

Lo que pasa 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 utiliza esto o similar?

+1

¿Qué quiere decir con 'robusto'? ¿Puedes ser más explícito en cuanto a lo que falta? ¿Qué intentaste? ¿Y con qué problema te topaste? Tuve problemas cuando comencé con NHibernate, por lo que me gustaría ayudar si es posible. –

17

Echa un vistazo Billy McCafferty's work. 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 utiliza 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); 
} 

}

+0

cosas buenas. Usando NH 3.2, funciona muy bien con un mod: tuve que cambiar 'HasOpenTransactionOn' para usar' transaction.IsActive'. [Aquí está el por qué] (http://stackoverflow.com/a/1007633/612265). –

+0

¡Oh, qué bueno! Muchas gracias – JoshBerke

4

recomiendo echarle un vistazo Rhino Commons biblioteca Ayende 's. El documentation es un poco escaso en este momento, pero una vez que esté en funcionamiento, trabajar con NHibernate será MUCHO más fácil.

5

He tenido un gran éxito en el pasado utilizando 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 del open session in view pattern.

Además, aunque nunca lo he probado, debería poder utilizar el marco anteriormente mencionado incluso si opta por no restablecer las ofertas de Spring.NET (concretamente IoC y AOP).

2

He escrito un blog post sobre esto donde utilizo la implementación web administrada de manejo de sesión contextual. Tal vez eso es lo que estás buscando?

1

Dos sugerencias:

  • HybridSessionBuilder de Jeffrey Palermo (jeffreypalermo.com/blog/use-this-nhibernate-wrapper-to-keep-your-repository-classes-simple)
  • Ver los ejemplos de código (ver específicamente Sesión 13) en el verano de NHibernate (www.summerofnhibernate.com)
0

Es posible que desee considerar la posibilidad de su DAL menos que ver con la gestión de sesiones de NHibernate mediante el aprovechamiento de NHibernate.Burrow (o la aplicación de un patrón similar a sí mismo)

"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 decide rodar su propia hay algunos enlaces útiles en la parte inferior de esta página:

Un término de búsqueda Google útil sería 'Gestión de la sesión de NHibernate' y 'Sesiones contextuales' ...

No hay escasez de ideas; podría decirse que hay demasiadas opciones, con suerte la opinión comenzará a gravitar alrededor de Burrow o algo así ...

Cuestiones relacionadas