Posted by: Cirilo Meggiolaro | 12/23/2008

Tip of the day #70 – Managing transactions with TransactionScope class

Manage transactions on the application side becomes easy with the usage of the TransactionScope class. It provides features to wrap a block of code into a single transaction, allows nested transactions and total control over how nested transactions correlate between them.

The class is available under the System.Transactions namespace but it is not added as default when you create your project. You need to add a reference to System.Transactions.dll assembly before use it.

Constructors

The TransactionScope class has 8 constructor overloads defined as listed below:

/// Parameterless constructor
public TransactionScope();

/// Accepts a transaction as parameter to be used.
public TransactionScope(Transaction transactionToUse);

/// Accepts a TransactionScopeOption enumerator item that describes
/// the requirements for the transaction being instantiated.

public TransactionScope(TransactionScopeOption scopeOption);

/// Accepts a transaction as parameter to be used and a timeout. After the
/// timeout has elapsed the transaction is aborted.
public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout);

/// Accepts a TransactionScopeOption enumerator item that describes
/// the requirements for the transaction being instantiated and a timeout.
/// After the timeout has elapsed the transaction is aborted.
public TransactionScope(TransactionScopeOption scopeOption, TimeSpan scopeTimeout);

/// Accepts a TransactionScopeOption enumerator item that describes
/// the requirements for the transaction being instantiated and a TransactionOptions
/// enumerator item that describes the settings to use if a new transaction is created.
public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions);

/// Accepts a transaction as parameter to be used, a timeout and COM+
/// interoperability settings. After the timeout has elapsed the
/// transaction is aborted.
public TransactionScope(Transaction transactionToUse, TimeSpan scopeTimeout, EnterpriseServicesInteropOption interopOption);

/// Accepts a TransactionScopeOption enumerator item that describes
/// the requirements for the transaction being instantiated, a TransactionOptions
/// enumerator item that describes the settings to use if a new transaction is created
/// and the COM+ interoperability settings.
public TransactionScope(TransactionScopeOption scopeOption, TransactionOptions transactionOptions, EnterpriseServicesInteropOption interopOption);

Methods

Only two methods are available under the TransactionScope class:

/// Commit all pending operations.
public void Complete();

/// Releases resources linked to the class.
public void Dispose();

How to…

Commit a transaction

When a transaction scope is created a Boolean flag is default to false indicating that the transaction has not completed yet. The Complete method is the responsible for requesting the commit of all operations defined within the transaction boundaries. It does not mean that the operations will be committed. If the transaction scope is disposed before the commit the transaction will be aborted.

Suggestion: Instantiate your TransactionScope object with using statements. For more details about the using statement, check the Tip #14.

The Complete method must be called only once. If called more than once a System.InvalidOperationException exception is thrown.

Rollback a transaction

Once there is no explicit method to rollback a transaction and the Complete method is the responsible for committing it to rollback you need…simply don’t call the Complete method.

The following code snippet shows the basic structure for implementing a transaction based on transaction scope:

using (TransactionScope transac = new TransactionScope())
{
    /// Perform your operations here

    /// Commits the transaction
    transac.Complete();
}

TransactionScopeOptions

You may realize that some of the constructor overloads accepts a TransactionScopeOptions enumerator option as parameter. The following options are available:

  • Required (Default): Uses an existing transaction if available. If a transaction has not been created yet, it creates a new one;
  • RequiresNew: Creates a new transaction;
  • Suppress: Defines all operations within the scope as no transaction participant.

Nesting transactions

Nested transactions are allowed but the way they correlate between each other is up to you. You should use the TransactionScopeOptions to define if they are going to execute under the same transaction. An inner transaction scope instantiated with the Required option will join the outer transaction while a inner one defined with RequiresNew option will run independently from the outer and finally a inner transaction scope defined with Suppress option will not participate in any transaction scope.

The following code shows a nested transaction between two different methods where the inner transaction scope joins the outer transaction scope:

private void MethodA()
{
    using (TransactionScope transac = new TransactionScope())
    {
    /// Perform your operations here

    /// Invokes the method B under the same transaction
    MethodB();

    /// Commits the transaction
    transac.Complete();
    }
}

private void MethodB()

{

    using (TransactionScope transac = new TransactionScope(TransactionScopeOption.Required))
    {
    /// Perform your operations here

    /// Commits the transaction
    transac.Complete();
    }
}

Important: Invoking the Complete method from within an inner transaction that joins the root transaction scope as the example above does not have any effect and will not commit the whole transaction.


Responses

  1. Cirilo, in which namespace we find that class?

  2. Hi Fadachi,

    You need to add a reference to the System.Transactions.dll assembly and import the System.Transactions namespace. I’ve changed the tip to explain that!

    Thanks for your comment!


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Categories

%d bloggers like this: