nhibernate transactionscope

NHibernate con TransactionScope



(6)

Lo anterior funciona bien siempre que esté utilizando un proveedor de conexión que admita el uso de un Administrador de transacciones liviano, como SQL Server 2005/2008.

Si está utilizando SQL Server 7/2000, todas sus transacciones se convertirán en Transacciones distribuidas, incluso si solo accede a una base de datos / recurso. Probablemente esto no sea lo que usted desearía en la mayoría de los casos, y será costoso en cuanto a rendimiento.

Por lo tanto, compruebe si su proveedor de conexión y combinación de servidor de base de datos son adecuados para su uso con TransactionScope.

¿Alguien puede darme una descripción general rápida del uso de TransactionScope con NHibernate? ¿Debo hacer algo especial con la sesión / IEnlistmentNotification / etc. para hacer que esto funcione? ¿Hay algún problema por el que deba preocuparme? Por ejemplo, ¿puedo reemplazar todas mis transacciones de hibernación?

var transaction = session.BeginTransaction(); try { // code transaction.Commit(); } catch (Exception) { transaction.Rollback(); }

¿con este?:

using (var scope = new TransactionScope()) { // code scope.Complete(); }


Además, si está utilizando TransactionScope, actualice a NHibernate 2.1. Es solo con 2.1 que NH realmente obtuvo una buena integración con TransactionScope.


He estado usando nHibernate 2.1 por un tiempo, y después de algunos problemas de producción y probar bastantes variaciones, nos hemos basado en el siguiente método, como evitar conexiones con NHibernate y TransactionScope :

using (var scope = new TransactionScope(TransactionScopeOption.Required)) { using (var session = sessionFactory.OpenSession()) using (var transaction = session.BeginTransaction()) { // do what you need to do with the session transaction.Commit(); } scope.Complete(); }

Como usamos MSMQ y WCF, tuvimos que usar la transacción ambiental.

Descubrimos que no usar session.BeginTransaction () causaba una pérdida de conexión. También descubrimos que volver a utilizar una sesión después de realizar una transacción provocaba una condición de carrera (nHibernate no es seguro para subprocesos y se producen errores DTSC / reversiones en una cadena de fondo).


He probado esto usando diferentes proveedores y simplemente funciona. Si no tiene "scope.Complete ()", la transacción se retrotraerá. Es posible que necesite tener MSDTC ejecutando las máquinas involucradas si hay más de un recurso duradero. En ese caso, MSDTC detectará automáticamente las transacciones ambientales de ADO.NET y administrará todo.


Según Fabio Maulo en comentarios relacionados con NH-2107 :

Puede usar TransactionScope y también debe continuar usando la transacción de NH. ¿Dónde ha leído que el uso de TransactionScope significa evitar el uso de la transacción de NH?

Hubiera supuesto que el uso explícito de las transacciones de NHibernate no es necesario, pero aparentemente esa es la mejor práctica


Creo que puede reemplazar las transacciones de NHibernate con esto siempre y cuando respete algunas restricciones, como algunos ya han dicho:

  • Use una versión razonablemente reciente de NHibernate ( > = 3.1 ).
  • El proveedor de datos ADO.NET subyacente debe admitir TransactionScope (ok para SQL-Server, Oracle> = 10 con ODP.NET).
  • Cree su sesión de NH dentro de TransactionScope para asegurarse de que se alista.
  • Maneje la descarga de NHibernate manualmente. Ver también aquí y aquí .
  • Prepárese para las transacciones distribuidas. Si crea varias sesiones en un ámbito, la transacción inicialmente local podría promocionarse a una transacción distribuida. Vi esto suceder incluso con las mismas cadenas de conexión en Oracle 11.2 DB usando ODAC 11.2.0.3.20. En SQL-Server 2008 R2 no promocionó. (Por cierto, uno puede ver esto mirando Transaction.Current.TransactionInformation.DistributedIdentifier, que es nulo para las transacciones locales.) Si bien las transacciones distribuidas tienen algunas ventajas, son más caras y les cuesta un poco más configurarlas. (Vea aquí cómo hacer esto para Oracle). Para asegurarse de que la promoción nunca ocurra en Oracle, configure " Promotable Transaction = local" en su cadena de conexión. Esto crea una excepción si algún código intenta hacerlo.

Espero que eso sea todo ;-)

PD: Agregué los detalles de Oracle porque eran mi preocupación y la de otros.