Pregunta Transacciones de NHibernate en lecturas


He leído la documentación y la explicación de por qué es altamente recomendable usar transacciones en operaciones de lectura en NH. Sin embargo, todavía no lo he "comprado" totalmente. ¿Alguien puede intentar explicarlo sin solo decirme a RTFM, que ya he hecho? ;)


32
2017-11-01 15:42


origen


Respuestas:


Esta publicación de uno de los autores podría tener tu respuesta:

Incluso si solo estamos leyendo datos,   quiere usar una transacción, porque   usando una transacción asegúrate de que obtenemos   un resultado consistente de la base de datos.   NHibernate supone que todo acceso a   la base de datos se realiza bajo un   transacción, y desaconseja firmemente   cualquier uso de la sesión sin una   transacción.

Dejando de lado el tema de seguridad de   trabajando con transacciones, el   suposición de que las transacciones son   costoso y tenemos que optimizarlos es   uno falso. Como ya fue mencionado,   las bases de datos siempre se ejecutan en   transacción. Y las bases de datos han sido   muy optimizado para trabajar con   actas. La pregunta es lo que sea   esto es por enunciado o por lote.   Hay una cierta cantidad de trabajo que necesita   que se debe hacer para crear y eliminar un   transacción, y tener que hacerlo por   declaración es en realidad más costoso que   haciéndolo por lote.


23
2017-11-01 16:13



Lo que han dicho los demás es cierto, pero no han señalado que el problema de no controlar las transacciones usted mismo es que si realiza varias operaciones de NHibernate sin una transacción explícita, cada una de estas operaciones tendrá lugar en transacciones separadas.

Por lo tanto, puede obtener inconsistencias entre las operaciones. Al iniciar explícitamente una transacción de NHibernate y luego realizar las operaciones en ella, se garantiza la coherencia en todas estas operaciones.

Esto es, por supuesto, cierto para CUALQUIER capa de acceso a datos que implícitamente inicie transacciones por usted si no lo hace. No está limitado a NHibernate.


8
2017-11-01 16:22



var fooIdFromDb = ExecuteQuery("Select Id from Foo where something = somethingelse");
var barsFromDb = ExecuteQuery("Select * from Bar where FooId = " + fooIdFromDB);

¿Qué pasa si alguna otra transacción elimina filas de la barra entre las dos consultas? Tendrá problemas con los datos fantasmas. Este no es un problema específico de NHibernate. Tendrá el mismo problema con cualquier otro tipo de acceso a la base de datos sin usar transacciones. Debe leer el manual sobre transacciones en general en lugar del manual de NHiberante.


6
2017-11-01 16:05



Vamos a centrarnos en lo que sucede si lo haría no usar transacciones. Es habitual, pero no obligatorio, cerrar la sesión al final del proceso, pero antes de comenzar a leer los datos (es decir, la vista). Este método se propaga bajo el término "Sesión abierta a la vista"(aunque obviamente tiene un patrón para evitar la lectura antes del cierre). Este patrón se usa a menudo en una aplicación web donde la sesión se abre cuando la solicitud llega y se cierra justo antes de escribir en la secuencia de respuesta.

(N) Hibernate necesita una sesión y una transacción. Cuando lee sin usar una transacción explícita, la transacción se configurará para usted. Cuando lee después de una transacción, el comportamiento depende de la configuración y el controlador de NH.

Tanto ODBC como JDBC no definen qué sucede cuando se cierra una conexión y hay datos no comprometidos o no enrollados. Cuando se vuelve a abrir la conexión, es posible que se inicie automáticamente una nueva transacción.

El uso del acceso no transaccional solo se puede usar junto con la configuración auto-commit explícitamente en la configuración NHibernate. Si no, se usa el predeterminado del controlador y puede funcionar o no funcionar.

En resumen, hay muchas deficiencias y comportamientos indefinidos cuando no se utilizan transacciones en lecturas. Funcionará a menudo, pero esto depende de la configuración, los patrones aplicados, los controladores. Hay una gran posibilidad de que consigas LazyInitializationExceptions, que es un resultado común de read after commit sin abrir una nueva transacción.

La "mejor práctica" es usar una transacción para lectura / escritura y otra para solo lectura. Esto se describe brevemente en el enlace anterior, sección "¿Puedo usar dos transacciones en una sesión?" Pero requiere más de su implementación.

No es solo "usar transacciones para leer", sino que también es: "usa la misma transacción que usas para escribir para leer". (y luego, si bien esto es cierto, la aplicación real dependerá de sus patrones actuales, cuántos niveles hay, almacenamiento en caché y configuración).

Actualizar: ampliado un poco, eliminó algunas ambigüedades


5
2017-11-01 16:32



además:
Renunciar al uso de transacciones explícitas tiene el efecto de anular la memoria caché de segundo nivel.


3
2017-11-01 16:31