2011-03-19 9 views
11

Voy a permitir que Ninject administre mi estado ISession y ITransaction en Fluent nHibnerate con el siguiente método de registro: me pregunto si es suficiente el control de las transacciones o si necesito ponerme esto en otro lugarDeje que Ninject administre mi estado de transacción, practique inquietudes

La idea es que cada ISession se crea en una solicitud, y que Ninject maneja la confirmación de todo lo hecho durante esa solicitud.

public class SessionModule : Ninject.Modules.NinjectModule 
{ 
    private static ISessionFactory sessionFactory; 

    public override void Load() 
    { 
     Bind<ISessionFactory>() 
      .ToMethod(c => CreateSessionFactory()) 
      .InSingletonScope(); 

     Bind<ISession>() 
      .ToMethod(c => OpenSession()) 
      .InRequestScope() 
      .OnActivation(session => 
      { 
       session.BeginTransaction(); 
       session.FlushMode = FlushMode.Commit; 
      }) 
      .OnDeactivation(session => 
      { 
       if (session.Transaction.IsActive) 
       { 
        try 
        { 
         session.Flush(); 
         session.Transaction.Commit(); 
        } 
        catch 
        { 
         session.Transaction.Rollback(); 
        } 
       } 
      }); 
    } 

    /// <summary> 
    /// Create a new <see cref="NHibernate.ISessionFactory"/> to connect to a database. 
    /// </summary> 
    /// <returns> 
    /// A constructed and mapped <see cref="NHibernate.ISessionFactory"/>. 
    /// </returns> 
    private static ISessionFactory CreateSessionFactory() 
    { 
     if (sessionFactory == null) 
      sessionFactory = Persistence.SessionFactory.Map 
       (System.Web.Configuration 
        .WebConfigurationManager 
        .ConnectionStrings["Local"] 
        .ConnectionString 
       ); 
     return sessionFactory; 
    } 

    /// <summary> 
    /// Open a new <see cref="NHibernate.ISession"/> from a <see cref="NHibernate.ISessionFactory"/>. 
    /// </summary> 
    /// <returns> 
    /// A new <see cref="NHibernate.ISession"/>. 
    /// </returns> 
    private static ISession OpenSession() 
    { 
     // check to see if we even have a session factory to get a session from 
     if (sessionFactory == null) 
      CreateSessionFactory(); 

     // open a new session from the factory if there is no current one 
     return sessionFactory.OpenSession(); 
    } 
} 

He examinado el tiempo de ejecución usando System.Diagnostics.Debug.WriteLine a escribir cuando ocurren las cosas, y lo hace aspecto que presentan está haciendo lo que quería que haga. Lo que le estoy preguntando, la comunidad, es si esta es una buena práctica o no. Aquí está mi entendimiento.

Innumerables horas de lectura en http://ayende.com/blog/default.aspx me han llevado a reevaluar gran parte de la forma en que manejo la sesión.

Una gran cantidad de excavación en la documentación nHibernate me dice que necesito usar ITransactioncada vez que pasa algo con mi base de datos.

La colocación de la gestión en un atributo se considera un error, ya que no se adhiere a la instrucción mencionada anteriormente.

Haciendo ITransaction por operación individual no es el proceso correcto, porque requeriría bien (a) mis controladores de tener acceso a la ISession o (B) Mi IRepository<T> tener la lógica ITransaction, que me han dicho en los anteriores preguntas no era una buena práctica.

La colocación de mi ITransaction de gestión en un HttpModule implica una sobrecarga no-lo necesite, ya que da mi conocimiento HttpContext del ISession y eso significa que tengo que hacer algún tipo de inyección en el HttpRequest (que yo puedo hacer uso de [Inject], pero no parece sabio)

Esto me ha llevado a esta conclusión.

  • Las transacciones deben comenzar cuando se solicita una ISession.
  • Todo lo que sucede en una sola petición está encapsulada por una ISession
  • Cuando un ITransaction se hace, tiene que ser cometido de manera que el segundo nivel de caché puede obtener sus resultados.

¿Alguien puede arrojar luz sobre esto? ¿Estoy finalmente en el camino correcto? ¿O todavía me he perdido el punto por completo?

+0

Me preguntaba si hay una manera de conectar en 'InRequestScope' para iniciar/confirmar la transacción ... Gracias por tu mensaje! – user1068352

Respuesta

2

No soy un experto (y no tengo experiencia con ninject), pero estoy de acuerdo con sus 3 conclusiones, y eso es lo que hago en mis proyectos.
Otra cosa que puedo agregar es que, en mi opinión, las transacciones deben controlarse EXPLÍCITAMENTE y por operación, y no globalmente (inicio y comienzo de la solicitud y confirmación al final) como sugiere su código.
Esto se debe a que creo que desea controlar el compromiso de comportamiento de su transacción o no (o tal vez ni siquiera iniciar, si no se necesita acceso a DB) para cada operación individualmente.
Lo que uso es una capa de gestión (o flujo de trabajo, si lo prefiere), que es responsable solo de eso. por ejemplo:

public class SomeManager : ManagersBase 
{ 
    public void DoSomething(DomainObject obj) 
    { 
     if (obj.Operation()) 
     { 
      using (ITransaction tx = Session.BeginTransaction()) 
      { 
       try 
       { 
        Session.Update(obj); 
        tx.Commit(); 
       } 
       catch (MeaningfulException ex) 
       { 
        //handle 
        tx.Rollback(); 
       } 
      } 
     } 
    } 
} 

esperanza esto ayuda

+0

Lamento no haber aceptado esto antes. Pensé que me había encargado de eso. Muchas gracias. – Ciel

Cuestiones relacionadas