2010-02-17 13 views
23

muchos ejemplos por ahí defensora de reversión explícita de transacciones de bases de datos, a lo largo de las líneas de:¿Es necesaria una reversión de transacción explícita?

using (var transaction = ...) 
{ 
    try 
    { 
     // do some reading and/or writing here 

     transaction.Commit(); 
    } 
    catch (SqlException ex) 
    { 
     // explicit rollback 
     transaction.Rollback(); 
    } 
} 

Sin embargo, tienden a hacer esto:

using (var transaction = ...) 
{ 
    // do some reading and/or writing here 

    transaction.Commit(); 
} 

Cuando se produce una excepción, sólo estoy contando en el retroceso implícito de las transacciones que no están comprometidas.

¿Hay algún problema al confiar en este comportamiento implícito? ¿Alguien tiene una razón convincente de por qué no debería hacerlo de esta manera?

+1

El código de ejemplo en su pregunta es posiblemente defectuoso ya que no se vuelve a lanzar. Tal vez la tendencia a olvidar eso es una razón para evitar este patrón? :) –

+0

¿Quién dice que quieres volver a lanzar? Revertir la transacción podría considerarse manejar la excepción, en muchos casos. –

+1

propones dos "opciones" diferentes. Para que el primero se comporte como el segundo, debe volver a tirar. Para ser equivalente, uno de los dos ejemplos debe cambiar. –

Respuesta

13

No, no es específicamente necesaria, sin embargo me ocurren 2 razones por las que podría ser una buena idea:

  • Claridad

Algunos podrían argumentar que el uso de transaction.Rollback() hace que sea más claro bajo qué circunstancias en que la transacción no será comprometida.

  • Liberación de bloqueos

Cuando se trata de transacciones es importante darse cuenta de las ciertas cerraduras solo serán entregados cuando la transacción se revierte o comprometido. Si está utilizando la declaración using, la transacción se retrotraerá cuando se deshaga de la transacción; sin embargo, si por algún motivo necesita realizar algún tipo de gestión de errores dentro del bloque using, puede ser ventajoso deshacer la transacción (eliminando las cerraduras) antes de realizar un manejo de errores complejo/lento.

1

Supongo que podría responderse que el primer enfoque es más legible para alguien que mantiene su código. La naturaleza explícita de la codificación hace que los objetivos sean claros y rápidos. Si bien la reversión implícita es clara para usted, y probablemente cualquiera que tenga más que un conocimiento pasajero del manejo de la transacción, puede no serlo para otros. Dicho esto, algunos comentarios corregirían rápidamente eso. La única preocupación es si la reversión implícita no es una característica documentada del objeto.

Por lo tanto, yo diría que, siempre que comente la operación y pueda confiar en la acción implícita, entonces no hay una buena razón para aplicar el enfoque explícito.

1

La conexión ADO.NET más correctamente escrita revertirá las transacciones no comprometidas explícitamente. Entonces no es estrictamente necesario.

El beneficio principal que veo de un Rollback() explícito lo llama la capacidad de establecer un punto de interrupción allí y luego inspeccionar la conexión o la base de datos para ver qué estaba pasando. También es más claro para los futuros mantenedores del código lo que sucede bajo diferentes rutas de ejecución.

0

Siempre que la transacción sea totalmente independiente en el bloque using(), ya está listo. Sin embargo, pueden surgir problemas si alguien recibe un objeto de transacción existente de un llamante. Pero ese es un escenario diferente ...

3

veo dos problemas con su uso:

  1. va a utilizar el método de la transacción Dispose() para deshacer una transacción no confirmada, la creación de una dependencia de la aplicación de un tercero de IDisposable. Es un riesgo insignificante en este caso, por supuesto, pero no es una buena práctica.
  2. Se está perdiendo la oportunidad de registrar y/o manejar la excepción. Además, captaría Exception no SqlException.
+0

La gestión de excepciones y el registro se producen más arriba en mi pila. La primera muestra no es mía, es lo que normalmente encuentras como código de gestión de transacciones de ejemplo. –

+0

IMO, el registro siempre debe ocurrir lo más cercano posible a la excepción. Con las transacciones siempre existe la posibilidad de una excepción, por lo que siempre debe haber un bloque try..catch. –

+2

Bueno, esa es tu opinión y tienes derecho a ella :) –

Cuestiones relacionadas