Pomelo.EntityFrameworkCore.MySql
Pomelo.EntityFrameworkCore.MySql copied to clipboard
Database Transaction is broken after Socket Exception (10054)
Steps to reproduce
The issue doesn't have exact steps to reproduce.
public async Task<T> ExecuteAsync<T>(Func<Task<T>> action)
{
IExecutionStrategy strategy = _context.Database.CreateExecutionStrategy();
return await strategy.ExecuteAsync(async () =>
{
await using IDbContextTransaction transaction = await _context.Database.BeginTransactionAsync();
try
{
T result = await action(); // action contains some code which is communicating with database
await transaction.CommitAsync();
return result;
}
catch
{
await transaction.RollbackAsync(); // throws System.ObjectDisposedException: Cannot access a disposed object.Object name: 'MySqlTransaction'.
throw;
}
});
}
Also, retry is enabled for the DB Context: options.EnableRetryOnFailure(5, TimeSpan.FromSeconds(3), null);
The issue
The issue takes place if one of the queries to a DB within a transaction is failed due to "System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host."
Then all the following requests to database are failed with the following error: "System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans"
And when I try to roll back the transaction it throws "System.ObjectDisposedException: Cannot access a disposed object. Object name: 'MySqlTransaction'."
Expected behavior: If a Socket exception has occurred, then the failed request should be retried according to the retry strategy settings and also, DB transaction should not be broken or disposed
StackTrace:
ERROR 2023-02-16 00:40:18,818 Microsoft.EntityFrameworkCore.Query [106] - An exception occurred while iterating over the results of a query for context type 'TestApp.Infrastructure.PersistenceTestDbContext'.
System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
at MySqlConnector.Protocol.Serialization.SocketByteHandler.WriteBytesAsync(ReadOnlyMemory`1 data, IOBehavior ioBehavior) in /_/src/MySqlConnector/Protocol/Serialization/SocketByteHandler.cs:line 125
--- End of stack trace from previous location ---
at MySqlConnector.Protocol.Serialization.ProtocolUtility.<WritePacketAsync>g__WritePacketAsyncAwaited|8_0(ValueTask`1 task, Byte[] buffer) in /_/src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs:line 546
at MySqlConnector.Core.ServerSession.SendReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 987
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 55
at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
at MySqlConnector.Protocol.Serialization.SocketByteHandler.WriteBytesAsync(ReadOnlyMemory`1 data, IOBehavior ioBehavior) in /_/src/MySqlConnector/Protocol/Serialization/SocketByteHandler.cs:line 125
--- End of stack trace from previous location ---
at MySqlConnector.Protocol.Serialization.ProtocolUtility.<WritePacketAsync>g__WritePacketAsyncAwaited|8_0(ValueTask`1 task, Byte[] buffer) in /_/src/MySqlConnector/Protocol/Serialization/ProtocolUtility.cs:line 546
at MySqlConnector.Core.ServerSession.SendReplyAsyncAwaited(ValueTask`1 task) in /_/src/MySqlConnector/Core/ServerSession.cs:line 987
at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList`1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/Core/CommandExecutor.cs:line 55
at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
ERROR 2023-02-16 00:40:18,821 My Test Service [106] - Error occurs on saving entity: An existing connection was forcibly closed by the remote host.
INFO 2023-02-16 00:40:18,821 My Test Service [106] - Execute another query
ERROR 2023-02-16 00:40:18,833 Microsoft.EntityFrameworkCore.Database.Command [106] - Failed executing DbCommand (0ms) ERROR 2023-02-16 00:40:18,834 Microsoft.EntityFrameworkCore.Query [106] - An exception occurred while iterating over the results of a query for context type 'Test.Infrastructure.Persistence.TestDbContext'.
System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans
at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext() System.InvalidOperationException: The transaction associated with this command is not the connection's active transaction; see https://fl.vu/mysql-trans
at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlCommand.cs:line 345
at MySqlConnector.MySqlCommand.ExecuteDbDataReader(CommandBehavior behavior) in /_/src/MySqlConnector/MySqlCommand.cs:line 278
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(Enumerator enumerator)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
ERROR 2023-02-16 00:40:18,839 Microsoft.EntityFrameworkCore.Database.Transaction [106] - An error occurred using a transaction.
ERROR 2023-02-16 00:40:18,841 My Test Service [106] - Error occurred: System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'MySqlTransaction'.
at MySqlConnector.MySqlTransaction.VerifyValid() in /_/src/MySqlConnector/MySqlTransaction.cs:line 281
at MySqlConnector.MySqlTransaction.RollbackAsync(IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlTransaction.cs:line 66
at Microsoft.EntityFrameworkCore.Storage.RelationalTransaction.RollbackAsync(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalTransaction.RollbackAsync(CancellationToken cancellationToken)
at Test.Infrastructure.Persistence.Services.TransactionService.<>c__DisplayClass3_0`1.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Test.Infrastructure.Persistence.Services.TransactionService.<>c__DisplayClass3_0`1.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.<>c__DisplayClass33_0`2.<<ExecuteAsync>b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteImplementationAsync[TState,TResult](Func`4 operation, Func`4 verifySucceeded, TState state, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.ExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Test.Infrastructure.Persistence.Services.TransactionService.ExecuteAsync[T](Func`1 action)
at Test.Domain.Core.Services.EntityN.AddEntity.MyService.AddEntity(Type1 a, Type2 b)
Further technical details
MariaDB version: 10.4 Operating system: Windows 10 Pomelo.EntityFrameworkCore.MySql version: 6.0.1