2010-01-04 18 views
10

TransactionScope espera una llamada a su método completo de la siguiente manera. De lo contrario, la transacción no se confirmará.¿Por qué TransactionScope no asume el éxito?

using(TransactionScope scope = new TransactionScope()) 
{ 
    /* Perform transactional work here */ 

    scope.Complete(); 
} 

¿No sería más apropiada una implementación que asuma el éxito? Esto significaría que se necesitaría menos código en el caso estándar (éxito).

En el caso de una excepción o una llamada a un método como 'Rollback' (este método no existe actualmente) la transacción podría revertirse.

using(TransactionScope scope = new TransactionScope()) 
{ 
    /* Perform transactional work here */ 

    if(problemOccurred) 
    { 
     scope.Rollback(); 
    } 
} 

Tenga en cuenta que el indicador de problemaOcurrido solo sería necesario en los casos en que el problema no dio lugar a una excepción. En este caso, la reversión se realizará automáticamente.

Estoy interesado en obtener más información sobre por qué se utilizó esta implementación.

Actualización: Hasta ahora, algunas de las respuestas han argumentado que se necesitaría un bloque try-catch si se utilizara la implementación que describí. Este no es el caso. La transacción se retrotrae automáticamente cuando no se maneja una excepción dentro del bloque de uso. Este es el caso tanto en la implementación existente como en la que describí. Consulte "Completar un alcance de transacción" en la sección here para obtener más detalles.

Actualización 2: Finalmente entiendo lo que se explica en las respuestas. Esta no es una construcción de lenguaje que podría haber sido interpretada de la manera que los diseñadores de lenguaje lo vieron, es una implementación del patrón IDisposable. Sin la llamada para completar el código dentro del método de eliminación, no tendría conocimiento de si se está llamando como resultado del código dentro del bloque de uso que se está ejecutando correctamente o porque se produjo una excepción. Estaba imaginando algo similar a lo siguiente donde tanto la transacción como la reversión son palabras clave.

transaction 
{ 
    /* Perform transactional work here */ 

    if(problemOccurred) 
    { 
     rollback; 
    } 
} 

Por supuesto, esto presenta problemas si las opciones de transacción tienen que pasarse a la TransactionScope.

+3

¿Por qué no se agrega automáticamente mi comentario cuando cambio de página, no debería tener que hacer clic en [Agregar comentario] ... – cjk

+1

De actualización - El * mecanismo * por el cual se retrotrae la transacción ante excepciones es que llegas al final del bloque de uso sin llamar a Commit. Es decir. ese comportamiento depende de la función exacta que desea eliminar. –

+0

Su "actualización" se refiere al estado actual del juego: si TransactionScope asumió el éxito, usted estaría cambiando esa situación. –

Respuesta

14

Esto significa que no necesita colocar un bloque de prueba/finalmente (o atrapar) manual (posiblemente con un indicador de "éxito") para el caso de falla. Intente volver a escribir el código anterior para deshacer el error, y observe cuánto más desordenado es ...

Básicamente, el comportamiento normal que se desea es comprometer solo si llega al final del bloque sin excepciones. La forma más simple de lograr eso es poner una llamada a método para indicar el éxito al final del bloque.

+0

No creo que se necesita un bloque try - ver mi comentario en respuesta ... http://stackoverflow.com/questions/1999461/why-doesnt-transactionscope-assume-success/1999475#1999475 ¿Estás de acuerdo? –

+1

No, porque estás proponiendo * cambiar * ese comportamiento. * Actualmente * no necesita un bloque try/catch precisamente por el comportamiento del que se queja: se asume un error a menos que se comprometa explícitamente. –

4

Si se hubiera elegido la otra implementación, ¡entonces la gente haría la pregunta inversa!

En serio, el comportamiento predeterminado en un mecanismo diseñado para proteger contra actualizaciones parciales o incorrectas seguramente tiene que ser no para confirmar, ¿no?

15

De esta manera, cada transacción se vería así:

using(TransactionScope scope = new TransactionScope()) 
{ 
    try 
    { 
    /* Perform transactional work here */ 
    } 
    catch (Exception) 
    { 
    scope.Rollback(); 
    throw; 
    } 
} 

¿Qué es más código.

Editar:

Todo lo demás es de estilo arriesgado o malo. Debe estar absolutamente seguro de que no hubo ningún error al confirmar. Al salir del bloque de uso, no sabes si lo dejas porque se lanza una excepción o porque acabas de llegar al final. Cuando llame al Complete, ya sabe.

La sintaxis del bloque de transacción ya es la más simple que puede hacer. Simplemente implemente la transacción sin ningún manejo especial de errores y comprométala al final. No tiene que preocuparse y retroceder cuando se produce un error. Considere que se pueden generar excepciones en casi todas las líneas de código (por ejemplo, NullReference, Overflows, InvalidOperation, etc.). Entonces, ¿qué podría ser más fácil que esto?

+1

Si utiliza el enfoque scope.Complete(), ¿cuándo ocurriría una reversión si estuviera justificado? – DOK

+1

Una excepción dentro del bloque de uso de TransactionScope revertiría automáticamente la transacción. Aquí una excepción de MSDN. "No poder llamar a este método anula la transacción, porque el administrador de transacciones interpreta esto como una falla del sistema, o equivalente a una excepción lanzada dentro del alcance de la transacción." Su bloque try es redundante. –

+0

Aquí está el enlace para la excepción. http://msdn.microsoft.com/en-us/library/ms172152.aspx –

3

Creo que la cantidad de código para escribir para tener éxito es, como dice @Jon Skeet, menos (y menos feo) de la manera actual. Sin embargo, desde el punto de vista de una transacción, creo que sería que desea que sea pesimista y suponga que, a menos que se indique explícitamente el éxito, lo retrotraerá. En mi opinión, cometer una transacción por error es un problema mucho peor que accidentalmente no poder realizar una transacción exitosa debido a un error de código.

Cuestiones relacionadas