Rafael Ferrato
Rafael Ferrato

Reputation: 23

QueryAsync returns intermittent errors 'This MySqlConnection is already in use.' and 'Connection must be Open; current state is Connecting'

I'm facing intermittent issues like:

This MySqlConnection is already in use.

and

Connection must be Open; current state is Connecting

They are hard to reproduce but in logs I can see a lot of them.

I'm using the library Pomelo.EntityFrameworkCore.MySql and running queries with dapper QueryAsync.

connectionstring:

Server=****;DataBase=*****;Uid=***;Pwd=****;default command timeout=0;SslMode=none;max pool size=1000;Connect Timeout=300;convert zero datetime=True;ConnectionIdleTimeout=5;Pooling=true;MinimumPoolSize=25

Code example:

var query = $@"
    SELECT 
    at.*, dpt.*, c.*, cnt.*, mEnc.*, atUsr.*, usr.*
    FROM Atendimento AS at
    INNER JOIN Departamento AS dpt ON at.DepartamentoId = dpt.Id
    INNER JOIN Canal AS c ON at.CanalId = c.Id
    LEFT JOIN Contato AS cnt ON at.ContatoId = cnt.Id
    LEFT JOIN MotivoEncerramento as mEnc ON at.MotivoEncerramentoId = mEnc.id
    LEFT JOIN (
    AtendimentoUsuario AS atUsr
    INNER JOIN Users AS usr ON atUsr.UserId = usr.Id
    ) ON at.Id = atUsr.AtendimentoId
    WHERE at.IdRef = '{idRef}'
    ORDER BY dpt.Id, c.Id, atUsr.Id, usr.Id;";

var atendimentos = await Dapper.SqlMapper.QueryAsync<Atendimento, Departamento, Canal, Contato, MotivoEncerramento, AtendimentoUsuario, Usuario, Atendimento>(
    _dbContext.Database.GetDbConnection(),
    query,
    (atendimento, departamento, canal, contato, motivoEncerramento, atUsuario, usuario) =>
    {
        atendimento.Departamento = departamento;
        atendimento.Contato = contato;
        atendimento.MotivoEncerramento = motivoEncerramento;
        atendimento.Canal = canal;
        atendimento.AtendimentoUsuarios = new List<AtendimentoUsuario>();
        if (atUsuario is not null)
        {
            atUsuario.Usuario = usuario;
            atendimento.AtendimentoUsuarios.Add(atUsuario);
        }

        return atendimento;
    });

var result = atendimentos.GroupBy(a => a.Id).Select(g =>
{
    var groupedAtendimento = g.First();
    if (g.Any(c => c.AtendimentoUsuarios.Count > 0))
    {
        groupedAtendimento.AtendimentoUsuarios = g.Select(a => a.AtendimentoUsuarios.SingleOrDefault()).ToList();
    }

    return groupedAtendimento;
});

atendimento = result.First();

This _dbContext.Database.GetDbConnection() method:

//
// Summary:
//     Gets the underlying ADO.NET System.Data.Common.DbConnection for this Microsoft.EntityFrameworkCore.DbContext.
//     This connection should not be disposed if it was created by Entity Framework.
//     Connections are created by Entity Framework when a connection string rather than
//     a DbConnection object is passed to the 'UseMyProvider' method for the database
//     provider in use. Conversely, the application is responsible for disposing a DbConnection
//     passed to Entity Framework in 'UseMyProvider'.
//
// Parameters:
//   databaseFacade:
//     The Microsoft.EntityFrameworkCore.Infrastructure.DatabaseFacade for the context.
//
// Returns:
//     The System.Data.Common.DbConnection
//
// Remarks:
//     See Connections and connection strings for more information.
public static DbConnection GetDbConnection(this DatabaseFacade databaseFacade)
{
    return GetFacadeDependencies(databaseFacade).RelationalConnection.DbConnection;
}

I see some people saying to use ToList() after the Select method but they weren't using dapper.

Upvotes: 1

Views: 247

Answers (0)

Related Questions