2011-01-07 6 views
14

Actualmente estoy teniendo una confusión con respecto al constructor del objeto TransactionScope.TransactionScopeOption - Obligatorio o RequiresNew

Digamos que los usuarios de mi sitio web pueden solicitar productos. Al enviar su solicitud, realizo una verificación de la cantidad actual que queda y si es mayor a cero, llevo a cabo la solicitud. Luego, al final, disminuyo la cantidad actual que queda.

Todo el proceso está dentro de una transacción, utilizando .NET transactionScope.

Después de leer varios artículos sobre el objeto .NET transactionScope, ahora estoy un poco confundido acerca del valor de la TransactionScopeOption que se utilizará para el constructor de transactionScope.

¿Cuál de los siguientes es más apropiado para el caso descrito anteriormente:

public void ProcessRequest() 
{ 
    TransactionOptions transactionOptions = new TransactionOptions(); 
    transactionOptions.IsolationLevel = IsolationLevel.Serializable; 
    using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.RequiresNew, transactionOptions)) { 
     // DB Query to verify if quantity is still greater than zero 
     // DB Query to request and decrement quantity 
     currentScope.Complete(); 
    } 
} 

O

public void ProcessRequest() 
{ 
    TransactionOptions transactionOptions = new TransactionOptions(); 
    transactionOptions.IsolationLevel = IsolationLevel.Serializable; 
    using (TransactionScope currentScope = new TransactionScope(TransactionScopeOption.Required, transactionOptions)) { 
     // DB Query to verify if quantity is still greater than zero 
     // DB Query to request and decrement quantity 
     currentScope.Complete(); 
    } 
} 

Tenga en cuenta que lo anterior es sólo una simplificación de mi problema real. Solo estoy interesado en conocer el valor correcto de TransactionScopeOption (RequiresNew o Obligatorio) para este caso.

Gracias por responder.

Respuesta

16

que depende de lo que desea que suceda si otro método llama ProcessRequestdentro de otra transacción:

public void SomeOtherMethod() { 
    using (TransactionScope ts = new TrasansctionScope()) { 
     // Another DB action 
     ProcessRequest(); 
     // Yet another DB action 
    } 
} 

Si desea ProcessRequest de usar la transacción creado por SomeOtherMethod, utilice TransactionScope.Required. Este es el valor predeterminado (y aún crea una transacción cuando la llamas sin haber creado otro alcance de transacción en la pila de llamadas).

Si desea forzar este método para usar siempre su propia (nueva) transacción, use TransactionScope,RequiresNew.

+0

En mi caso, el método processRequest en sí nunca participará dentro de otra transacción. Sólo estoy mirando para asegurar que después de una petición ejecuta: "DB consulta para comprobar si la cantidad es aún mayor que cero" en el momento en que se ejecuta: "DB de consulta para solicitar y decremento de la cantidad" la cantidad aún no ha llegado a cero debido a otra solicitud, ejecutando el mismo método ProcessRequest. Así que supongo que el valor predeterminado es TransactionScope.Required. –

+2

Definitivamente, de lo contrario, estarías (involuntariamente) dando a entender que había algo especial sobre ProcessRequest que requería que utilizara su propia transacción. –

+0

Ok. Gracias por la rápida respuesta. –

5

Entiendo que su método no será llamado en otra transacción. Pero en caso de que así sea, así es como eliges TransactionScopeOption.

Si el contenido escrito a la base de datos por ProcessRequest no puede ser revocada por cualquier persona que llama, utilice RequiresNew, que se inicia una nueva transacción paralelo a la creada por la persona que llama (si lo hay), y la nueva transacción no es administrado por la persona que llama de ninguna manera. Lo mejor es pensar que la transacción no puede anidarse, ya sea usar una transacción existente o crear una nueva. ¡La transacción no está anidada!

Si se puede anular el contenido escrito en la base de datos por ProcessRequest, use Required. Sin embargo, esta opción no es transparente; quien llama a ProcessRequest debe saber que ProcessRequest puede retroceder porque si el destinatario retrotrae la transacción ambiental, la persona que llama no puede realizar ninguna operación sql, de lo contrario, la excepción "La operación no es válida para el estado de la transacción". será arrojado. Probablemente sea mejor consultar siempre System.Transactions.Transaction.Current.TransactionInformation.Status antes de ejecutar cualquier consulta, ya que no sabrá si un destinatario cree furtivamente una transacción y la haya devuelto.

Usted puede encontrar la siguiente tabla útil. enter image description here

Cuestiones relacionadas