In our solution we have section like this:
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
var task1 = _repository1.SaveAsync(dto);
var task2 = _repository2.SaveAsync(dto1);
await Task.WhenAll(task1 , task2).ConfigureAwait(false);
transaction.Complete();
}
Each of the repo creates a new DbContext with new connection
And from time to time we have MS DTC error:
System.Data.SqlClient.SqlException: Current Microsoft Distributed Transaction Coordinator (MS DTC) transaction must be committed by remote client.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)\r\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)\r\n at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)\r\n at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
MS DTC is configured properly, PS command "Test-Dtc -LocalComputerName "$env:COMPUTERNAME" -Verbose" returns:
VERBOSE: ": Firewall rule for "RPC Endpoint Mapper" is enabled."
VERBOSE: ": Firewall rule for "DTC incoming connections" is enabled."
VERBOSE: ": Firewall rule for "DTC outgoing connections" is enabled."
VERBOSE: server: AuthenticationLevel: NoAuth
VERBOSE: server: InboundTransactionsEnabled: True
VERBOSE: server: OutboundTransactionsEnabled: True
VERBOSE: server: RemoteClientAccessEnabled: True
VERBOSE: server: RemoteAdministrationAccessEnabled: True
VERBOSE: server: XATransactionsEnabled: True
VERBOSE: server: LUTransactionsEnabled: True
I found similar topic - TransactionScope() and parallel query execution, unfortunately, there is a no explanation of this error, and no solution. I don't have enough score to ask author, did he find a solution and what was a real issue.
Of course I can change the logic to:
using (var transaction = new TransactionScope(TransactionScopeAsyncFlowOption.Enabled))
{
await _repository1.SaveAsync(dto).ConfigureAwait(false);
await _repository2.SaveAsync(dto1).ConfigureAwait(false);
transaction.Complete();
}
But I want to understand, what is the reason, why MS DTC complains when asynchronous execution is used in TransactionScope