work unit new framework ejemplo begintransaction c# .net transactionscope

c# - new - unit of work transactionscope



C#controlando una transacción a través de múltiples bases de datos (2)

Supongamos que tengo una aplicación Windows Form que se conecta a n bases de datos, con n conexiones abiertas simultáneamente.

Lo que estoy buscando es hacer una transacción con todas esas bases de datos de una sola vez.

Por ejemplo, si tuviera 2 conexiones de base de datos:

using (ITransaction tx1 = session1.OpenTransaction()) { using (ITransaction tx2 = session2.OpenTransaction()) { // Do the query thingy here } }

Escribir todo lo que está bien al principio, pero las cosas se vuelven un tanto redundantes cuando quiero consultar aquí y allá, y sin mencionar la posibilidad de agregar una nueva conexión.

Lo que quería era hacer un bucle de toda la sesión registrada y envolverla en un servicio, probablemente algo como esto:

class TransactionManager { private ISession[] _sessions; public TransactionManager(string[] connectionStrings) { // Initialize the sessions here } public function DoTransaction(string query) { foreach (ISession session in _sessions) { // What to do here? Using? Try-catch? } } }

Si tuviera que usar el uso en el bucle foreach , significaría que si la conexión A fue exitosa pero la conexión B no lo fue, entonces solo la conexión B sería retrotraída.


Parece que puedes estar reinventando TransactionScope . Hacer todo esto bajo una unidad de trabajo es sencillo *:

using (TransactionScope scope = new TransactionScope()) { ... Do Stuff with Connection 1 using SqlDataReader ... Do Stuff with Connection 2 using Entity Framework ... Do Stuff with Connection 3 on another Oracle Database ... And for good measure do some stuff in MSMQ or other DTC resource scope.Complete(); // If you are happy }

Stuff no necesitan estar en línea en absoluto, pueden estar en una clase diferente o en un ensamblaje diferente. No hay necesidad de registrar explícitamente las conexiones de la base de datos o de la cola con el TransactionScope : todo sucede de forma automagically , siempre que los recursos que use puedan enlistarse en una transacción ambiental .

Ahora la letra pequeña:

  • * Cada vez que use más de una conexión de base de datos al mismo tiempo, o cadenas de conexión diferentes o múltiples tecnologías, esto requerirá una confirmación en dos fases y una escalada a una transacción DTC para garantizar el ACID en todos los recursos. El propio DTC tiene mucha más letra pequeña y plantea muchos más desafíos en una red corporativa , como firewalls , clustering , configuración de seguridad y bugs .
  • Sin embargo, con las transacciones Lightweight en MS Sql Server, si puede mantener todas sus conexiones utilizando la misma base de datos y la misma configuración de cadena de conexión, y cerrar cada conexión antes de abrir la siguiente, puede evitar el DTC .

  • Mantener una transacción a través de múltiples recursos ACID invariablemente mantendrá bloqueos en estos recursos, hasta que la transacción se confirme o se revierta. A menudo, esto no favorece la buena vecindad en una empresa de alto volumen, así que asegúrese de considerar las consecuencias del bloqueo.

  • Si el Stuff se realiza a través de varios subprocesos, deberá atar en DependentTransaction

  • Un último punto que vale la pena mencionar es que el nivel de aislamiento predeterminado con TransactionScope es Serializable, que es propenso a los interbloqueos. En la mayoría de los escenarios no críticos, es probable que pueda soltar esto en Leer confirmado .


use TransactionScope, se encargará de comprometer o deshacer todas las transacciones incluidas:

using (var ts = new TransactionScope()) { ... // your old code ts.Complete() }