Pomelo.EntityFrameworkCore.MySql: "Cannot Open when State is Connecting." with AddDbContextPool.
Steps to reproduce
I faced problem on production. I can’t reproduce this problem in simple example.
Also not all requests failed with this problem.
Problem reproduced only with AddDbContextPool()
. With AddDbContext()
all are fine.
The issue
In this case I add new entity using AddAsync()
and then I call SaveChangesAsync()
I fixed problem using AddDbContext()
.
Cannot Open when State is Connecting.
at MySqlConnector.MySqlConnection.OpenAsync(Nullable`1 ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlConnection.cs:line 445
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 Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlRelationalConnection.OpenAsync(CancellationToken cancellationToken, Boolean errorsExpected)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionAsync(IsolationLevel isolationLevel, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalConnection.BeginTransactionAsync(CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(IEnumerable`1 commandBatches, IRelationalConnection connection, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(StateManager stateManager, Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
at Dodo.Accounting.EfRepository.Repositories.MaterialConsumption.OrderRepository.CreateAsync(Order order, CancellationToken ct) in /home/runner/work/accounting/accounting/src/Dodo.Accounting.EfRepository/Repositories/MaterialConsumption/OrderRepository.cs:line 52
Further technical details
MySQL version: 5.7.28 Operating system: Linux (docker mcr.microsoft.com/dotnet/aspnet:6.0) Pomelo.EntityFrameworkCore.MySql version: 6.0.0 Microsoft.AspNetCore.App version: 6
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 24
Everything’s rocking 🚀
Fixed in MySqlConnector 2.1.1.
@nelsonprsousa Should work pretty much the same as for projects without using
Microsoft.Build.CentralPackageVersions
:Update the
Nuget.config
file with the nightly build feed. Then update the referenced package version (in your case located in yourPackages.props
file) to the respective version from the newly added feed (e.g. 6.0.1-servicing.1.ci.20220114125709+sha.1974429).@nelsonprsousa Took a week longer than planned, but the latest nightly build is feature complete in regards to
6.0.1
and references MySqlConnector2.1.2
, in case you want to give it a spin.Working as expected 🚀
Thank you
— EDIT
Will the dependency be updated to MySqlConnector (>= 2.1.1) in the next release?
Yes, the dependency is MySqlConnector (>= 2.0.0) so just add it to your csproj.
@vaital3000 Thanks for the repro; this is very helpful. The problem is that MySqlConnection isn’t setting the state to
Closed
here: https://github.com/mysql-net/MySqlConnector/blob/73b3ddefd8682bfb0dad620ebb487158250f989e/src/MySqlConnector/MySqlConnection.cs#L411-L421Seems like @vaital3000 found what’s causing the issue. When passing a
CancellationToken
toDbContext
async operations and cancelling it (pretty common in ASP.NET Core) causes the existingDbContext
instances in the pool to get messed up for future uses.@mguinness @bgrainger Here is a repository with a simple console app that reproduces the issue consistently. It kind of replicates a high throughput ASP.NET 6 web app. As soon as an async task (
ToListASync()
,CountAsync()
,AnyAsync()
, etc.) is cancelled via aCancellationToken
,Cannot Open when State is Connecting.
starts being thrown in subsequentDbContext
uses.Hope this helps.
I reproduced this error in this case. Errors happened after calling cts.Cancel(). But I’m not sure what this is the same case that I see in production.
CancellationToken wasn’t cancelled in production.
PS: I updated example. If I set small value for poolSize in AddDbContextPool, I saw error for both task. With ef core 5 I saw problem only with “Group1” task.
@bgrainger Experiencing exactly the same issue after migrating to Pomelo.EntityFrameworkCore.MySql 6 / EFCore 6 and .NET 6. When using
AddDbContextPool()
in an ASP.NET 6 web application, after a few hundred requests, most DbContext operations throwSystem.InvalidOperationException: Cannot Open when State is Connecting.
Replacing
AddDbContextPool()
withAddDbContext()
solves the issue. This problem was not present in Pomelo.EntityFrameworkCore.MySql 5 / EFCore 5 with .NET 5.