svidgen
svidgen

Reputation: 14302

Is TransactionScope implicitly applied until explicitly Completed?

Consider the following methods.

DoA()
{
  using (TransactionScope scope = new TransactionScope)
  {
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
      connection.Open();
      SqlCommand command = new SqlCommand(query, connection);
      command.ExecuteNonReader();

      DoB();    

      scope.Complete();
    }
  }
}

DoB()
{
  using (TransactionScope scope = new TransactionScope)
  {
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
      connection.Open();
      SqlCommand command = new SqlCommand(query, connection);
      command.ExecuteNonReader();

      DoC();

      scope.Complete();
    }
  }
}

DoC()
{
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
    connection.Open();
    SqlCommand command = new SqlCommand(query, connection);
    command.ExecuteNonReader();
  }
}

If we call DoA(), do the subsequent interactions in DoB() and DoC() run in the context of DoA()'s transaction as it pertains to SQL Server? Does DoC() run in the context of both DoA() and DoB()'s transactions?

(Or am I grossly misunderstanding something?)

Upvotes: 5

Views: 1158

Answers (2)

Andy
Andy

Reputation: 8562

All code logically will be a single transaction. The nested scopes don't necessarily create a new transaction (unless you use RequiresNew), so it will be a single transaction. Now, each scope must vote to complete the transaction so in your second scope if you remove the Complete, should cause the entire transaction to rollback.

DoC will be part of the transaction as well; the ambient transaction will detect the new connection and be enlisted automatically.

Please read all of the details here which explain the behavior of enrolling in the ambient transaction and the different options Requires, RequiresNew, and Suppress.

Also note that if your connections don't use EXACTLY same connection string, this will automatically promote the entire transaction to a Distributed Transaction. Just something to watch out for.

Upvotes: 5

svidgen
svidgen

Reputation: 14302

Edited per Andy's comments:

It seems as though something like this would occur on the SQL server:

BEGIN TRANSACTION A

  -- do A's work

  -- B does NOT create a new transaction

    -- do B's work

    -- do C's work

COMMIT TRANSACTION A

The following occurs if new TransactionScope(TransactionScopeOption.RequiresNew) is used in DoB().

BEGIN TRANSACTION A

  -- do A's work

  BEING TRANSACTION B

    -- do B's work

    -- do C's work

  COMMIT TRANSACTION B
COMMIT TRANSACTION A

Upvotes: 2

Related Questions