TransactionScopeOption what's the difference between the options?

7

I was doing a search on the options for TransactionScope and found the following settings:

Required
A transaction is required for the scope. If it already exists, it uses an environment transaction. Otherwise, it creates a new transaction before entering the scope. This is the default value.

RequiresNew
A new transaction is always created for the scope.

Suppress
The environment transaction context will be suppressed when you create the scope. All operations within the scope are performed without an environment transaction context.


In what context does each apply best?

If the Suppress option causes operations within the scope not to be performed in a transaction, then why declare a transaction? What is the use of this option?

    
asked by anonymous 18.10.2016 / 13:23

2 answers

3

Beginning with your final question, Suppress , by itself, is not very useful:

using(TransactionScope ambiente = new TransactionScope())
{
    using(TransactionScope suprimida = new TransactionScope(TransactionScopeOption.Suppress))        
    {
        // erros aqui não cancelam a transação 'ambiente' 
    }
}
That is, a single suppressed transaction within another transaction will cause errors within the deleted transaction to not abort the transaction environment (a transaction is considered to be environment when it is the root, or first, of all transactions of a connection), which means that the transaction environment is completed successfully.

However, consider the following case:

using(TransactionScope ambiente = new TransactionScope())
{
    using(TransactionScope requer = new TransactionScope(TransactionScopeOption.Required))        
    {
        // erros aqui CANCELAM a transacção 'ambiente' 
    }

    using(TransactionScope suprimida = new TransactionScope(TransactionScopeOption.Suppress))        
    {
        // erros aqui NÃO cancelam a transacção 'ambiente' 
    }
}

In this case, consider having two separate pieces of code, one vital for your application (eg, saving a customer's data) and another non-vital piece of code (write a log for the database).

In the case shown, even if the log writing fails, the client data is safeguarded because the code responsible for saving them is inside a transaction associated with the ambiente transaction and both will be completed at the end of block ambiente .

In turn, the logs writing, even within the ambiente block, is inside a block whose transaction was suppressed, which means that if it fails, errors will not cause a rollback of the ambiente transaction.

Finally, the third option, RequireNew indicates that even if there is an environment transaction, the code within your block must be completed and saved regardless of the transaction environment.

using(TransactionScope ambiente = new TransactionScope())
{
    using(TransactionScope requer = new TransactionScope(TransactionScopeOption.Required))        
    {
        // erros aqui CANCELAM a transacção 'ambiente' 
    }

    using(TransactionScope requerNova = new TransactionScope(TransactionScopeOption.RequiresNew))        
    {
        // erros aqui NÃO CANCELAM a transacção 'ambiente' 
        // mas CANCELAM a transacção 'requerNova' 
    }

    using(TransactionScope suprimida = new TransactionScope(TransactionScopeOption.Suppress))        
    {
        // erros aqui NÃO cancelam a transacção 'ambiente' 
    }
}

(response based on in this article ) p>     

15.08.2017 / 09:39
4

In the article on Transactions of Israel Aéce , says:

  

If the method supports transaction and it is automatically created,   any transactional feature that you access within this operation,   auto-enlistment ) and, with this, the whole   any manipulation will be managed by the transaction. This means   that there is no need to write code to create the transaction,   because the WCF already guarantees this; regardless of the transaction created   by WCF, you can perfectly, within the method, create a block   transactional through class TransactionScope , that one of your   constructor accepts one of the options specified in the enumerator    TransactionScopeOption , which allows you to "interact" with the environment   transaction. The possible values are:

     
  • Required : A transaction is required. If the transaction exists, the process will be part of it; otherwise, a new transaction will be   created.

  •   
  • RequiredNew : A new transaction is required. Regardless of whether or not a transaction exists, it will always be created   a new one.

  •   
  • Suppress : No transaction is required. Regardless of whether or not a transaction exists, the task will not be involved in a   transacted environment.

  •   

If the scope is instantiated with Required an environment transaction is present, the scope joins the transaction. If, on the other hand, there is no environment transaction, the scope creates a new transaction and becomes the root scope. This is the default value. When Required is used, the code within the scope does not have to behave differently be it the root or just associating the environment transaction. It should operate identically in both cases.

If the scope is instantiated with RequiresNew , it is always the root scope. It starts a new transaction, and your transaction becomes the new transaction environment within the scope.

If the scope is instantiated with Suppress , it is never part of a transaction, regardless of whether an environment transaction is present. An instance instantiated with this value always has null as its environment transaction.

The above options are summarized in the table :

 TransactionScopeOption |   Transação de ambiente   |    Escopo faz parte
------------------------|---------------------------|------------------------------
    Required            |           Não             |   Nova transação (será a raiz)
    Requires New        |           Não             |   Nova transação (será a raiz)
    Suppress            |           Não             |   Nenhuma transação
    Required            |           Sim             |   Transação de ambiente
    Requires New        |           Sim             |   Nova transação (será a raiz)
    Suppress            |           Sim             |   Nenhuma transação

It's interesting to know when using Required or RequiresNew , in this answer of stackoverflow in English shows this. I translated to leave the complete answer.

To know when to use Required or RequiresNew , based on the example, depends on what you want to happen if another method calls ProcessRequest inside another operation:

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

If you want ProcessRequest to use the operation created by SomeOtherMethod , use TransactionScope.Required . This is the default (and still creates a transaction when you call it without having created another transaction scope up the call stack). If you want to force this method to always use your own (new) transaction, use TransactionScope.RequiresNew .

References:

18.10.2016 / 14:10