Executing 4 stored procedures (using .NET 8 + EF Core) always stops due to a transaction timeout after approx. 15 minutes although the transaction scope timeout is set to 1 hour! In addition, the command timeout of the DBContext is set to 45 minutes.
Why does it fail after 15 minutes? Do I need to set another (timeout) setting?
Code (executed in a MediatR request handler):
<code> private static readonly string logLineStartedExecutingMethod = "Started executing method {MethodName}";
private static readonly string logLineFinishedExecutingMethod = "Finished executing method {MethodName} - {RecordCount}";
using var trans = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(1, 0, 0), TransactionScopeAsyncFlowOption.Enabled);
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestA");
var resultA = await _procedureRepository.UspTestAAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestA", resultA?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestB");
var resultB = await _procedureRepository.UspTestBAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestB", resultB?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestC");
var resultC = await _procedureRepository.UspTestCAsync(request.UserName ?? "Onbekend", default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestC", resultC?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestD");
// ERROR!!! Transaction timeout after approx. 15 minutes
var resultD = await _procedureRepository.UspTestDAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestD", resultD?.ToString() ?? "0");
trans.Complete();
</code>
<code> private static readonly string logLineStartedExecutingMethod = "Started executing method {MethodName}";
private static readonly string logLineFinishedExecutingMethod = "Finished executing method {MethodName} - {RecordCount}";
using var trans = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(1, 0, 0), TransactionScopeAsyncFlowOption.Enabled);
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestA");
var resultA = await _procedureRepository.UspTestAAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestA", resultA?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestB");
var resultB = await _procedureRepository.UspTestBAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestB", resultB?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestC");
var resultC = await _procedureRepository.UspTestCAsync(request.UserName ?? "Onbekend", default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestC", resultC?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestD");
// ERROR!!! Transaction timeout after approx. 15 minutes
var resultD = await _procedureRepository.UspTestDAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestD", resultD?.ToString() ?? "0");
trans.Complete();
</code>
private static readonly string logLineStartedExecutingMethod = "Started executing method {MethodName}";
private static readonly string logLineFinishedExecutingMethod = "Finished executing method {MethodName} - {RecordCount}";
using var trans = new TransactionScope(TransactionScopeOption.RequiresNew, new TimeSpan(1, 0, 0), TransactionScopeAsyncFlowOption.Enabled);
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestA");
var resultA = await _procedureRepository.UspTestAAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestA", resultA?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestB");
var resultB = await _procedureRepository.UspTestBAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestB", resultB?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestC");
var resultC = await _procedureRepository.UspTestCAsync(request.UserName ?? "Onbekend", default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestC", resultC?.ToString() ?? "0");
_logger.LogInformation(logLineStartedExecutingMethod, "UspTestD");
// ERROR!!! Transaction timeout after approx. 15 minutes
var resultD = await _procedureRepository.UspTestDAsync(default, cancellationToken);
_logger.LogInformation(logLineFinishedExecutingMethod, "UspTestD", resultD?.ToString() ?? "0");
trans.Complete();
Exception
<code> System.Transactions.TransactionException: The operation is not valid for the state of the transaction.
---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
at Microsoft.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at Microsoft.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at CBS.IHG.EHOConnector.adapters.Data.StoredProcedures.DbContextExtensions.SqlQueryAsync[T](DbContext db, String sql, Object[] parameters, CancellationToken cancellationToken)
</code>
<code> System.Transactions.TransactionException: The operation is not valid for the state of the transaction.
---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
at Microsoft.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at Microsoft.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at CBS.IHG.EHOConnector.adapters.Data.StoredProcedures.DbContextExtensions.SqlQueryAsync[T](DbContext db, String sql, Object[] parameters, CancellationToken cancellationToken)
</code>
System.Transactions.TransactionException: The operation is not valid for the state of the transaction.
---> System.TimeoutException: Transaction Timeout
--- End of inner exception stack trace ---
at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Guid promoterType)
at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification)
at Microsoft.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx)
at Microsoft.Data.ProviderBase.DbConnectionPool.PrepareConnection(DbConnection owningObject, DbConnectionInternal obj, Transaction transaction)
at Microsoft.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection)
at Microsoft.Data.ProviderBase.DbConnectionPool.WaitForPendingOpen()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenInternalAsync(Boolean errorsExpected, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.FromSqlQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at CBS.IHG.EHOConnector.adapters.Data.StoredProcedures.DbContextExtensions.SqlQueryAsync[T](DbContext db, String sql, Object[] parameters, CancellationToken cancellationToken)