Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

634
Vistas
Uso de TransactionScope en torno a un procedimiento almacenado con transacción en SQL Server 2014

Estoy usando C# y ADO.Net con TransactionScope para ejecutar una transacción en una aplicación ASP.Net. Se supone que esta transacción guarda algunos datos en varias tablas y luego envía un correo electrónico a los suscriptores.

Pregunta : ¿es un uso válido de TransactionScope , cuando incluye una llamada a un procedimiento almacenado que tiene su propia transacción en SQL Server 2014, o debo eliminar las declaraciones de transacciones SQL, es decir, begin tran , commit tran y rollback tran declaraciones almacenadas? procedimiento que se llama dentro de este TransactionScope ?

El código C# para este escenario y también el código T-SQL del procedimiento almacenado se mencionan a continuación.

Código C# usando TransactionScope :

 try { using (TransactionScope scope = new TransactionScope()) { using (SqlConnection connection1 = new SqlConnection(connectString1)) { // Opening the connection automatically enlists it in the // TransactionScope as a lightweight transaction. connection1.Open(); // SaveEmailData is a stored procedure that has a transaction within it SqlCommand command1 = new SqlCommand("SaveEmailData", connection1); command1.CommandType = CommandType.StoredProcedure; command1.ExecuteNonQuery(); } //Send Email using the helper method EmailHelper.SendCustomerEmails(customerIds); // The Complete method commits the transaction. If an exception has been thrown, // Complete is not called and the transaction is rolled back. scope.Complete(); } } catch( Exception ex) { Logger.Log(ex); }

T-SQL del procedimiento almacenado SaveEmailData :

 SET NOCOUNT ON BEGIN TRY DECLARE @emailToUserId BIGINT BEGIN TRAN -- //update statement. detail statement omitted UPDATE TABLE1... --update statement. detail statement omitted UPDATE TABLE2... IF @@trancount > 0 BEGIN COMMIT TRAN END END TRY BEGIN CATCH IF @@TRANCOUNT > 0 BEGIN ROLLBACK TRAN END EXEC Error_RaiseToADONET END CATCH
over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Sí, TransactionScope aún puede funcionar cuando se empaqueta una transacción TSQL BEGIN / COMMIT TRANSACTION o una ADO SqlConnection.BeginTransaction . Al envolver una sola conexión, el comportamiento es similar a anidar transacciones en Sql :

  • @@TranCount se incrementará en cada BEGIN TRAN

  • COMMIT TRAN simplemente disminuirá @@TRANCOUNT . La transacción solo se confirmará si @@TRANCOUNT llega a cero.

Sin embargo:

  • ROLLBACK TRAN anulará toda la transacción (es decir, @@TRANCOUNT a cero ), a menos que esté utilizando Puntos de guardado (es decir, SAVE TRANSACTION xx ... ROLLBACK TRANSACTION xx ).
  • Al usar procedimientos almacenados, recibirá un error si el @@TRANCOUNT TRANCOUNT de la conexión difiere al salir del SPROC del valor que tenía al ingresar al SPROC.

Como resultado, normalmente es mucho más fácil dejar la semántica de transacciones a TransactionScope y eliminar cualquier lógica manual BEGIN TRAN / COMMIT TRAN para que no sature su TSQL.

Editar - aclaración de los comentarios a continuación

  • En el caso del OP, el SPROC NO se ha escrito teniendo en cuenta las transacciones anidadas (es decir, ya sea envuelto por una transacción externa Sql o .Net), específicamente, el ROLLBACK en el bloque BEGIN CATCH cancelará toda la transacción externa y probablemente causará más errores en el TransactionScope externo ya que no se ha cumplido la regla @@TRANCOUNT . Se debe observar unpatrón de transacción anidado como este si un SPROC necesita operar tanto en forma de transacción anidada como independiente.

  • SavePoints no funciona con transacciones distribuidas , y TransactionScope puede escalar fácilmente a una transacción distribuida, por ejemplo, si está utilizando diferentes cadenas de conexión o controlando otros recursos bajo el alcance de la transacción.

Como resultado, recomendaría refactorizar el PROC en un caso interno/núcleo 'feliz', llamando a este proceso interno desde Transaction Scope y haciendo cualquier manejo de excepción y reversión allí. Si también necesita llamar al proceso desde Ad Hoc Sql, proporcione un Proc contenedor externo que tenga el manejo de excepciones:

 -- Just the happy case. This is called from .Net TransactionScope CREATE PROC dbo.InnerNonTransactional AS BEGIN UPDATE TABLE1... UPDATE TABLE2 .... END; -- Only needed if you also need to call this elsewhere, eg from AdHoc Sql CREATE PROC dbo.OuterTransactional AS BEGIN BEGIN TRY BEGIN TRAN EXEC dbo.InnerNonTransactional COMMIT TRAN END TRY BEGIN CATCH -- Rollback and handling code here. END CATCH END;
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda