2012-05-10 11 views
5

A realice una acción en mi aplicación MVC que tenga id y devuelva el nombre de una persona.NHibernate - Mejor práctica para simplemente seleccione

¿Cuál es la mejor práctica para eso? Estoy siguiendo los consejos de NHProf, pero el código suena un poco extraño o algo para mí.

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
{ 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     return session.Query<Person>().Where(x => x.Id == id).Select(x => x.Name).SingleOrDefault(); 
     tran.Rollback(); 
    } 
} 
+0

no puedo entender por qué se sugiere una transacción ... –

+0

¿qué quieres saber? –

+1

No usaría 'OpenStatelessSession', la sesión sin estado es para escenarios masivos e ignora la caché L1. En lugar de hacer una consulta de linq, simplemente llamaría a '.Load (1)' o '.Get (1)' que expresa intenciones más que una consulta de linq. – Andreas

Respuesta

4

La página de alerta NHProf lo explica bastante bien creo -

http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions

Básicamente es decir, si no se las arreglan transacciones a sí mismo, la base de datos creará una "transacción implícita" y concesionarios - comprometerse para cada declaración, incluidas las consultas. La idea errónea es que las transacciones son útiles solo para las operaciones de inserción/actualización.

En su ejemplo anterior, no es un gran problema ya que su transacción solo ejecuta una sola declaración de todos modos. Si su método estaba ejecutando varias declaraciones, sería una buena práctica envolverlas en una transacción.

+0

OK, pero para métodos simples, ¿debo seguir NHProf y crear una transacción o no? – Zote

+1

La respuesta solo es parcial, siempre ___ siempre debe deformar su consulta de base de datos en una transacción y, de hecho, sería un problema incluso si ejecuta una sola instrucción. ¡Las transacciones implícitas son costosas! y NH no usará la memoria caché L2 sin una transacción. – Andreas

-1

La siguiente es cómo iba a acercarse a este selecto:

using (var session = Helper.SessionFactory.OpenStatelessSession()) 
    using (var tran = session.BeginTransaction(IsolationLevel.ReadCommitted)) 
    { 
     try 
     { 
      string personName = session.Query<Person>() 
      .Where(x => x.Id == id) 
      .Single(x => x.Name); 

      tran.Commit(); 
      return personName; 
     } 
     catch(Exception ex) 
     { 
      // handle exception 
      tran.Rollback(); 
     } 
    } 

Este SO respuesta da buenos consejos para tratar con transacción se confirma:

NHibernate - Is ITransaction.Commit really necessary?

Con respecto a su LINQ esta es una Artículo interesante sobre cómo no abordar las consultas utilizando la sintaxis del estilo del método de extensión:

http://compiledexperience.com/blog/posts/how-not-to-use-linq

+0

-1 para capturar todo, hacer trabajo redundante (usar y probar capturar). – Andreas

+0

@Andreas, hasta donde yo sé, no tiene forma de procesar una excepción lanzada y la opción es usar una prueba redundante o eliminar manualmente. Además, ¿cómo implementaría el manejo de errores en este caso ya que hay varias capas que podrían arrojar un error (NHibernate, ADO.NET, LINQ). –

+2

http://stackoverflow.com/questions/6418992/is-it-a-better-practice-to-expllicitlycall-transaction-rollback-or-let-an-except y para excepciones http://stackoverflow.com/questions/426346/is-this-a-bad-practice-to-catch-a-non-specific-exception-such-as-system-exceptio http://stackoverflow.com/questions/114658/catching-base- exception-class-in-net http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx y no me diga que puede manejar correctamente stackoverflows, sin memoria exc con su 'tran.Rollback();'. – Andreas

0

No cree varias sesiones a través de una solicitud HTTP, idealmente lo que necesita hacer es abrir una sesión y una transacción correspondiente en el ámbito de solicitud y utilizar esta sesión en todas sus acciones.

Aquí está una entrada de blog que explica cómo lograrlo: http://hackingon.net/post/NHibernate-Session-Per-Request-with-ASPNET-MVC.aspx

Yo sugeriría el uso de un contenedor COI y crear una clase que crea la sesión para usted y el alcance de esta clase en el ámbito de la petición.

Hay un montón de recursos en la web para abordar este problema .. .. Google que

+0

Si bien una sesión por solicitud es un buen consejo, no es una regla difícil y rápida, y tener una transacción por solicitud es un mal consejo, claro y simple. – Spivonious

Cuestiones relacionadas