Transactionscopeoption what is the difference between the options?

Asked

Viewed 961 times

7

I was doing some research on the options for Transactionscope and found the following settings:

Required
A transaction is required for 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 deleted when creating the scope. All operations within the scope are performed without an environment transaction context.


In what context each best applies?

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

2 answers

4

In the article on Israel Aéce transactions, says:

If the transaction support method is created, automatically, any transactional resource you access within this operation, will automatically be listed (self-cenlistment) and with it all and any handling will be managed by the transaction. This means that there is no need to write code to create the transaction, for the WCF already guarantees it; regardless of the transaction created by WCF, you can perfectly, within the method, create a block transactional across the class TransactionScope, that one of his constructs accepts one of the options specified in the enumerator TransactionScopeOption, which allows you to "interact" with the environment existing transaction. 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 maid.

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

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

If the scope is instantiated with Required an environment transaction is present, the scope links 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 need to have a different behavior be the root or just associating the environment transaction. He must operate identically in both cases.

If the scope is instantiated with RequiresNew, is always the root scope. It starts a new transaction, and your transaction becomes the new ambient transaction 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 instantiated scope with that value will always have null as your transaction environment.

The above options are summarised in 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 to use Required or RequiresNew, in that reply stackoverflow shows this. I translated to make the answer more complete.

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

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

If you want the 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 scope of the transaction up to the call stack). If you want to force this method to always use your own (new) transaction, use TransactionScope.RequiresNew.

References:

  • 1

    Se você quer ProcessRequest para utilizar a operação criado pela SomeOtherMethod, use TransactionScope.Required and Se você quer que ele para forçar esse método para usar sempre sua própria transação (novo).. That explanation got confused. @taisbevalle

  • 1

    @rubStackOverflow, improved.

3


Starting with your final question, Suppress, on its own, not much use:

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 transaction deleted within another transaction will cause errors within the deleted transaction not to abort the ambient transaction (a transaction is considered to be environment when it is the root, or the first, of all transactions on a connection)which means that the ambient transaction is successfully completed.

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 that you have two distinct pieces of code, one vital to your application (e. g, save data from a client) and another piece of non-vital code (write a log to the database).

in the demonstrated case, even if the written log failed, customer data is backed up because the code responsible for saving it is inside a transaction associated with the transaction ambiente and both will be completed at the end of the block ambiente.

In turn, the writing of logs, though inside the block ambiente, is within a block whose transaction has been deleted, which means that if it fails, the errors will not cause the transaction to go back ambiente.

Finally, the third option, RequireNew indicates that even if there is an ambient transaction, the code within its block must be completed and stored independently of the ambient transaction.

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 in this article)

  • 1

    Your reply is perfect @Omni, thank you very much! Just a small detail for the block requerNova, in the example given ended up being like Required instead of RequiresNew.

  • 1

    @Jedaiasrodrigues thank you for the correction :) Evil of the copy-Paste

Browser other questions tagged

You are not signed in. Login or sign up in order to post.