Question

Process order:

  • Saga message handler receives first message containing data items.
  • Message handler uses business objects that has it's own database transaction.
  • If items are updated OK, database transaction commits and saga completes.
  • Saga message handler receives second message containing data items.
  • Message handler throws exception trying to open new database transaction as above.

Error message:

System.Data.SqlClient.SqlException (0x80131904): Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.

Stack Trace:

2012-01-27 14:07:47,407 [Worker.9] ERROR 

LawCover.LISServices.LISBankAgent.SagaMessageHandler [(null)] - Exception details
System.Data.SqlClient.SqlException (0x80131904): Distributed transaction completed. Either enlist this session in a new transaction or the NULL transaction.
   at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
   at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransaction(TransactionRequest transactionRequest, String name, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
   at System.Data.SqlClient.SqlInternalConnection.BeginSqlTransaction(IsolationLevel iso, String transactionName)
   at System.Data.SqlClient.SqlConnection.BeginTransaction(IsolationLevel iso, String transactionName)
   at System.Data.SqlClient.SqlConnection.BeginTransaction()
   at LawCover.LIS.DataAccess.ConnectionManager.BeginTransaction()
   at LawCover.LISServices.LISBankAgent.LISMethods.AddCreditCardPaymentSettlementScheduleItemsAndReceiptsIntoLISForCurrentMessages(BankResponseFileProcessed message) in C:\Projects\LIS Improvements\LIS\Source\LISServices\LISBankAgent\LISMethods.cs:line 53
   at LawCover.LISServices.LISBankAgent.SagaMessageHandler.Handle(BankResponseFileProcessed message) in C:\Projects\LIS Improvements\LIS\Source\LISServices\LISBankAgent\SagaMessageHandler.cs:line 177

There's quite a lot of code covering the above flow but I'm happy to post what will be useful.

Was it helpful?

Solution

I peeled back the transactions to find that the saga handler was opening another database connection and by default, the connection is enlisted in the DTC. I added "Enlist=false" to the connection string as the exceptions thrown by database need to be caught and dealt accordingly rather than collapsing the distributed transaction. Now it behaves as expected.

Thanks for your input, I'll be revisiting the code and taking your comments on-board.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top