2010-01-06 15 views
41

Soy nuevo en NHibernate y he visto algunos problemas al cerrar las sesiones prematuramente. Lo he resuelto temporalmente reutilizando sesiones en lugar de abrir una sesión por transacción. Sin embargo, tenía la impresión de que las sesiones de apertura cada vez que las necesitaban eran el enfoque recomendado para la gestión de la vida de la sesión. ¿No?¿Cuál debería ser el tiempo de vida de una sesión de NHibernate?

So; ¿Cuál es la forma recomendada de manejar sesiones? ¿Cuál debería ser su vida? Una sesión pr transacción? ¿Una sesión única para manejar todo? ¿O que?

Editar:

Nota que mi arquitectura de la aplicación es una aplicación de escritorio la comunicación con un servicio del lado del servidor, que es lo que hace todo el manejo de bases de datos, utilizando NHibernate + Fluido. (Si esto hace alguna diferencia ...)

+2

En tu pregunta http://stackoverflow.com/questions/2011950/nhibernate-mappings-issue-when-referencing-class-lazy-load-issue me pediste que investigara esta nueva pregunta, pero te veo ' Ya he recibido una amplia cobertura. Opino algunas de las opiniones aquí, pero tenga en cuenta que parece que las sesiones y las transacciones se entremezclan en la discusión, mientras que esas son cosas diferentes. Además, un grupo de sesiones o una sesión desencadenada por tiempo de espera puede ser beneficioso en términos de rendimiento, pero es difícil de configurar y acertar. También tenga en cuenta que bajo la capucha, la agrupación de conexiones se utiliza independientemente de su patrón elegido. – Abel

+0

Gracias por su comentario Abel. En ejemplos, he visto que las sesiones y transacciones a menudo comparten la misma duración, pero como se ve en la pregunta a la que se hace referencia, a veces puede ser un problema. Espero que la gente haya respondido a "duración de la sesión", no a "duración de la transacción". la impresión de que este es el caso. – stiank81

Respuesta

26

Desea una estrategia de administración de sesión que permita que su aplicación funcione de manera efectiva y aproveche las ventajas que le ofrece NHibernate, especialmente el almacenamiento en caché y la carga diferida.

Crear sesiones es un proceso poco costoso y requiere poca RAM o CPU por adelantado, por lo que no debe preocuparse por conservar o volver a utilizar las sesiones (de hecho, volverlas a utilizar puede llevar a un lado desagradable e inesperado -efectos). La fábrica de sesiones es lo más caro y debe construirse una vez y solo una vez en el inicio de la aplicación.

La regla general es la siguiente: la duración de la sesión tiene que ser lo suficientemente largo que no tiene objetos persistido dando vueltas en su alcance después de que termine la sesión.

Una vez que termine la sesión, todo cambio rastreo de objetos que obtuvo de esa sesión se detiene, por lo que esos cambios no ser salvo a menos que deliberadamente volver a conectar ese objeto a una nueva sesión. Por lo tanto, la sesión debería permanecer activa mientras existan los objetos que obtenga de ella. En una aplicación web, eso generalmente significa una sesión para cada solicitud; en WinForms, una sesión para cada formulario.

En su caso, con un servicio (supongo que está funcionando como un servicio de Windows) haciendo el trabajo NHibernate, es posible que desee considerar la posibilidad de una sesión creada para cada nueva solicitud de la aplicación de escritorio que consume, y disponerla cuando esa solicitud ha sido atendida. Sin saber exactamente cómo se ejecuta su servicio y qué mecanismo utiliza la aplicación de escritorio para hablar con él (¿remoto? ¿WCF? ¿Llamar a SOAP?) En realidad, no puedo ser más específico.

(Existen algunas excepciones a esta regla general: supongamos que tiene un conjunto de objetos persistentes que representan un recurso compartido al que otro código hará referencia pero no cambia, puede cargarlos por adelantado al inicio de la aplicación y salir ellos se desconectaron de allí en adelante)

Si encuentra que el rendimiento es lento bajo tal estrategia, es posible que solo esté hablando demasiado con la base de datos y su gráfico de objetos sea complejo; mira second-level caching en este caso.

+0

¡Gracias!En cuanto a mi servicio, estoy usando WCF, actualmente con soap - running como una aplicación de consola, pero no creo que esto suponga ninguna diferencia, por lo que fuiste lo suficientemente específico. Parece razonable tener una sesión para cada solicitud. Actualmente solo estoy usando una sesión donde se está ejecutando la transacción, y parece que hay algunos datos referenciados que no se cargan durante la transacción y que fallan porque la sesión está cerrada. – stiank81

6

Una sesión debe corresponder a una unidad de trabajo. La sesión debe permanecer activa mientras trabaja con los objetos recuperados o persistentes utilizando esa sesión.

2

No hay una sola respuesta que se adapte a todas las situaciones. La sesión 13 de Summer of Nhibernate presenta una buena visión general del problema.

0

Gran parte del marco NHibernate y Microsoft ADO.NET Entity Framework son similares. Aquí hay un artículo muy bueno sobre cómo debe controlar una línea de vida ObjectContext en ADO.NET EF.

http://blogs.msdn.com/alexj/archive/2009/05/07/tip-18-how-to-decide-on-a-lifetime-for-your-objectcontext.aspx

debería aplicarse a las sesiones de NHibernate también.

+1

En mi opinión, dado que EF 1.0/3.5 no es compatible con la carga diferida automática basada en proxy, las diferencias entre EF y NHibernate con respecto a este problema son demasiado grandes para compartir consejos de manera efectiva. El tiempo de vida de ObjectContext en EF es más fácil de administrar porque EF no es tan rico en funciones. –

+0

Tiene razón en que EF 1.0 no es compatible, pero EF 2.0 sí. Este artículo parece aplicarse a ambos. –

11

En una aplicación web, debe tener una sesión por solicitud. Esto le da un control total sobre la duración de la sesión y simplifica el manejo de errores.

En una aplicación de escritorio, recomiendo usar una sesión por presentador (o formulario si lo prefiere). Para citar Ayende en su MSDN Magazine article:

La práctica recomendada para aplicaciones de escritorio es utilizar una sesión por forma, de manera que cada formulario en la aplicación tiene su propia sesión. Cada forma generalmente representa un trabajo distinto que el usuario desea que realice, por lo que la duración de la sesión coincide con la duración de la vida del formulario bastante bien en la práctica. El beneficio adicional es que ya no tiene un problema con pérdidas de memoria, porque cuando cierra un formulario en la aplicación , también se deshace de la sesión . Esto haría que todas las entidades que fueron cargadas por la sesión sean elegibles para reclamar por el recolector de basura (GC).

Existen razones adicionales para que prefieren una sola sesión por formulario. Puede aprovechar el seguimiento de cambios de NHibernate, por lo que eliminará todos los cambios de la base de datos cuando confirmen la transacción.También crea una barrera de aislamiento entre los diferentes formularios, por lo que puede confirmar los cambios en una sola entidad sin preocupándose por los cambios en otras entidades que se muestran en otros formularios .

+0

"sesión por operación" es bastante vago. Debe mencionar "sesión por solicitud" –

Cuestiones relacionadas