Get TransactionScope to work with async / await

Yann picture Yann · Nov 24, 2012 · Viewed 29.7k times · Source

I'm trying to integrate async/await into our service bus. I implemented a SingleThreadSynchronizationContext based on this example http://blogs.msdn.com/b/pfxteam/archive/2012/01/20/10259049.aspx.

And it works fine, except for one thing: TransactionScope. I await for stuff inside the TransactionScope and it break the TransactionScope.

TransactionScope doesn't seems to play nice with the async/await, certainly because it store things in the thread using ThreadStaticAttribute. I get this exception :

"TransactionScope nested incorrectly.".

I tried to save TransactionScope data before queuing the task and restore it before running it but it doesn't seems to change a thing. And TransactionScope code is a mess, so it's really hard to understand what's going on there.

Is there a way to make it work ? Is there some alternative to TransactionScope?

Answer

ZunTzu picture ZunTzu · Jul 8, 2013

In .NET Framework 4.5.1, there is a set of new constructors for TransactionScope that take a TransactionScopeAsyncFlowOption parameter.

According to the MSDN, it enables transaction flow across thread continuations.

My understanding is that it is meant to allow you to write code like this:

// transaction scope
using (var scope = new TransactionScope(... ,
  TransactionScopeAsyncFlowOption.Enabled))
{
  // connection
  using (var connection = new SqlConnection(_connectionString))
  {
    // open connection asynchronously
    await connection.OpenAsync();

    using (var command = connection.CreateCommand())
    {
      command.CommandText = ...;

      // run command asynchronously
      using (var dataReader = await command.ExecuteReaderAsync())
      {
        while (dataReader.Read())
        {
          ...
        }
      }
    }
  }
  scope.Complete();
}