2009-10-25 7 views
5

Esta noche he estado repasando mis conocimientos, tratando de superar 4 años de malas prácticas de programación debido a la compañía para la que estaba trabajando. Una de las cosas con las que me topé recientemente fue System.Transactions. Después de leer sobre ellos durante las últimas horas, creo que tengo una comprensión adecuada de cómo funcionan y por qué querrías usarlos. Sin embargo, todos los ejemplos que he visto muestran T-SQL en línea que se llama desde dentro de la transacción.Sistema de mezcla.Transacciones con SqlTransactions

Casi uso procedimientos almacenados exclusivamente al hacer acceso a la base de datos y los procedimientos almacenados existentes están todos envueltos en sus propias SqlTransacciones. Ya sabes, usar 'Begin Tran' y luego retroceder o comprometerse. Si un Stored Proc llama a otro proceso almacenado, también crea una transacción y los Compromisos aumentan hasta que el externo se compromete o retrocede. Funciona genial.

Así que ahora mi pregunta es, si quería comenzar a usar System.Transactions en mi código, con el simple propósito de monitorear tareas sucesivas de la base de datos que no pueden anidarse en un solo procedimiento almacenado, ¿cómo funciona eso con el ¿SqlTransactions existentes que ya tengo en mis procesos almacenados?

¿Usaré System.Transactions en mi código solo agregaré una capa más de protección antes de que esté realmente comprometido, o porque estoy cometiendo explícitamente en mi SqlTransaction - los datos se conservarán independientemente de la confirmación o el retroceso en el código basado ¿transacción?

+0

La respuesta aceptada sobre esta pregunta es incorrecta. Usar una transacción Sql dentro de un System.Transaction causa un comportamiento involuntario (concretamente, una transacción Sql NO participa en el System.Transaction externo). Hacer esto neutraliza eficazmente su transacción. –

+0

Gracias por hacer estas correcciones, Bill. 7 años después y ni siquiera recuerdo si terminé implementando algo que lo necesitaba, pero es bueno tener la respuesta correcta marcada. :) – WesleyJohnson

Respuesta

4

No, las transacciones de System.Transactions y Sql no se mezclan.

Y cito, "Do not Mix Them" del siguiente artículo de MSDN: https://msdn.microsoft.com/en-us/library/ms973865.aspx.

Las transacciones Sql no participan en el sistema externo.Transacción de la forma que desee. Las transacciones Sql que fallen o reviertan no causarán otras actividades dentro del Sistema. Transacción para deshacer.


Este ejemplo muestra los fenómenos:

using (var tx = new TransactionScope()) 
{ 
    using (var con = new SqlConnection($"{connectionstring}")) 
    { 
     con.Open(); 

     using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value1', '{Guid.NewGuid()}'); rollback;", con)) 
     { 
      // This transaction failed, but it doesn't rollback the entire system.transaction! 
      com.ExecuteNonQuery(); 
     } 

     using (var com = new SqlCommand($"set xact_abort on; begin transaction; INSERT INTO dbo.KeyValueTable VALUES ('value2', '{Guid.NewGuid()}'); commit;", con)) 
     { 
      // This transaction will actually persist! 
      com.ExecuteNonQuery(); 
     } 
    } 
    tx.Complete(); 
} 

Después de ejecutar este ejemplo en un almacén de datos vacío se debe notar que los registros de la segunda operación de SQL son de hecho comprometidos, cuando la estructura de la C# el código implicaría que no deberían serlo.


En pocas palabras, no debe mezclarlos. Si está organizando múltiples transacciones Sql dentro de una aplicación, debe usar System.Transactions. Lamentablemente, eso significaría eliminar su código de transacción de todos sus procedimientos almacenados, pero, por desgracia, es necesario ya que con un modelo mixto no puede garantizar la integridad de sus datos.

+0

Gracias, he cambiado la respuesta aceptada. – WesleyJohnson

+0

¿Qué pasa si se utilizó una transacción explícita de ADO.Net para el SqlCommand y esa transacción se enlistó en la transacción XA (o eso es posible)? ¿Eso cancelaría la transacción XA? – STLDeveloper

-1

Funciona bien, si sus transacciones internas dentro de los procesos almacenados se comprometen, todo se confirmará. Si uno de ellos retrocede, todo lo que esté dentro de la transcation externa retrocederá. Magia pura. :)

+0

Excelente. Eso es lo que estaba esperando y parecía la respuesta lógica, simplemente no quería suponer. Muy apreciado. – WesleyJohnson

+0

Esto es definitivamente incorrecto. Ver: https://msdn.microsoft.com/en-us/library/ms973865.aspx –

+0

La respuesta aceptada ha sido modificada. :) – WesleyJohnson

Cuestiones relacionadas