Intermittent dapper error "Object reference not set to an instance of an object" when running QueryAsync

56 views Asked by At

I'm facing a really strange issue with Dapper.SqlMapper.QueryAsync:

Query:

_dbSession.OpenCon();
        
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>(
            _dbSession.Connection,
        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();
    
_dbSession.Dispose();

Most times it is running fine but sometimes it returns Object reference not set to an instance of an object with this StackTrace:

at MySqlConnector.MySqlDataReader.ActivateResultSet(CancellationToken cancellationToken) in //src/MySqlConnector/MySqlDataReader.cs:line 108 -|-
at MySqlConnector.MySqlDataReader.CreateAsync(CommandListPosition commandListPosition, ICommandPayloadCreator payloadCreator, IDictionary2 cachedProcedures, IMySqlCommand command, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /_/src/MySqlConnector/MySqlDataReader.cs:line 456 -|- at MySqlConnector.Core.CommandExecutor.ExecuteReaderAsync(IReadOnlyList1 commands, ICommandPayloadCreator payloadCreator, CommandBehavior behavior, Activity activity, IOBehavior ioBehavior, CancellationToken cancellationToken) in /
/src/MySqlConnector/Core/CommandExecutor.cs:line 56 -|- at MySqlConnector.MySqlCommand.ExecuteReaderAsync(CommandBehavior behavior, IOBehavior ioBehavior, CancellationToken cancellationToken) in //src/MySqlConnector/MySqlCommand.cs:line 331 -|-
at MySqlConnector.MySqlCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken) in /
/src/MySqlConnector/MySqlCommand.cs:line 323 -|-
at Datadog.Trace.ClrProfiler.CallTarget.Handlers.Continuations.TaskContinuationGenerator4.SyncCallbackHandler.ContinuationAction(Task1 previousTask, TTarget target, CallTargetState state) in /project/tracer/src/Datadog.Trace/ClrProfiler/CallTarget/Handlers/Continuations/TaskContinuationGenerator`1.cs:line 143 -|-
at Dapper.SqlMapper.MultiMapAsync[TFirst,TSecond,TThird,TFourth,TFifth,TSixth,TSeventh,TReturn](IDbConnection cnn, CommandDefinition command, Delegate map, String splitOn) in /_/Dapper/SqlMapper.Async.cs:line 921 -|-
at Comzada.Infra.Data.Repository.CustomersRepository.GetByIdRefAsync(String idRef, Boolean forceCacheUpdate) in /home/centos/compile_server/Comzada.Infra.Data/Repository/CustomersRepository.cs:line 263

The strange thing is that it is intermittent and hard to figure out. I thought that it could be something with the connection but I always open/dispose it.

Any help will be very appreciated.

ConnectionString:

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

DbSession added to Startup.cs:

services.AddScoped<DbSession>();

DbSession.cs:

using System;
using System.Data;
using Microsoft.Extensions.Configuration;
using MySqlConnector;
using static Dapper.SqlMapper;

namespace ***.Infra.Data.Context
{
    public sealed class DbSession : IDisposable
    {
        public IDbConnection Connection;
        private readonly IConfiguration _configuration;

        public DbSession(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        public void OpenCon(bool masterInstance = false)
        {
            var conStr = masterInstance ? "MySqlConnectionString" : "MySqlConnectionStringRead";

            Connection = new MySqlConnection(_configuration.GetValue<string>($"ConnectionStrings:{conStr}"));
            Connection.Open();
        }

        public void Dispose() => Connection?.Dispose();
    }
}
0

There are 0 answers