I updated some data access code to wrap some operations in a TransactionScope. The operations are async methods running some Dapper execute statements to write data to a SQL Server database. Something like:
public async Task InserData(SourceData sourceData)
{
using (var transactionScope = new
TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
using (IDbConnection connection = new
SqlConnection(this.ConnectionString))
{
connection.Open();
await InsertSomeData(sourceData.Registers, connection);
await InsertMoreData(sourceData.Deposits, connection);
transactionScope.Complete();
}
}
}
Anyway, I wire up a unit test to this method and it fails with this message:
Result Message:
Test method ExtractSourceDataTest.CanStart threw exception:
System.InvalidOperationException: A TransactionScope must be disposed on the same thread that it was created.
As usual, Google to the rescue. I found a nice blog post that explains the issue, https://particular.net/blog/transactionscope-and-async-await-be-one-with-the-flow. Basically, TransactionScope was not made to operate asynchronously across threads, but there is a work around for that. Microsoft released a fix, TransactionScopeAsyncFlowOption.Enabled. I went from a zero
using (var transactionScope = new TransactionScope())
to a hero
using (var transactionScope = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
Now, if this would have been turned on by default I wouldn’t of had this little problem… talking to you Microsoft. I’m sure there is some backward compatibility issue or other quirk that makes default enable difficult, but I’m ranting anyway.
Conclusion
This is awesome, but I basically just enabled a distributed transaction and that scares me. You do not know the trouble I have seen with distributed transactions. Hopefully, its not that bad since we are distributing across processes on the same machine and not over the network, but scary none the least.