How to know the exact line of a Nullreferenceexception error when creating a new instance of an object with multiple properties

Asked

Viewed 152 times

4

That’s a question I’ve always had, but now I’ve decided to ask.

If when creating a new object (as in the example below, Occurrencereport), the Nullreferenceexception error is generated, the stack trace does not tell me exactly in which object property the error occurred. There is a way to enable or discover this?

var ocorrencias = _db.Ocorrencia.AsEnumerable().Select(ocorrencia => new OcorrenciaRelatorioDTO
{
    Id = ocorrencia.Id,
    Ocorrencia = ocorrencia.NumOcorrencia,
    Protocolo = ocorrencia.Protocolo,
    Tipo = ocorrencia.Tipo?.Descricao,
    Cliente = ocorrencia.EmpresaCliente.sigla.ToUpper(),
    UF = ocorrencia.EmpresaCliente.estado,
    Grupo = ocorrencia.EmpresaCliente.nomeGrupo,
    Representante = ocorrencia.EmpresaRepresentante.nomeFantasia.ToUpper(),
    Filial = ocorrencia.EmpresaFilial.sigla.ToUpper(),
    Km = ocorrencia.Deslocamento,
    Motivo = ocorrencia.Motivo?.Descricao,
    DataHoraAbertura = ocorrencia.DataHoraAbertura,
    Equipamento = ocorrencia.NomeEquipamentoFocus,
    Serie = ocorrencia.Serie,
    DataHoraAgendada = ocorrencia.DataHoraAgendada,
    DataHoraAtendimento = ocorrencia.DataHoraAtendimento,
    DataHoraFechamento = ocorrencia.DataHoraFechamento,
    Status = ocorrencia.Status?.Descricao,
    Solucao = ocorrencia.Solucao?.Descricao,
    Observacao = ocorrencia.Observacao,
    Conclusao = ocorrencia.Conclusao?.Descricao,
    OrdemServico = ocorrencia.OrdemServico,
    Orcamento1 = ocorrencia.NumOrcamento,
    Orcamento2 = ocorrencia.NumOrcamento2,
    CedulasProcessadas = ocorrencia.CedulasProcessadas,
    Tecnico = ocorrencia.OcorrenciaTecnico?.FirstOrDefault().Nome,
    CobrarDeslocamento = ocorrencia.CobrarDeslocamento ? "Sim" : "Não",
    CobrarAtendimento = ocorrencia.CobrarAtendimento ? "Sim" : "Não",
}).ToList();

4 answers

6


You can instantiate the object as an example below. So you can debuggar (debug) line-by-line:

OcorrenciaRelatorioDTO ocorrenciaRel = new OcorrenciaRelatorioDTO;

ocorrenciaRel.Id = ocorrencia.Id;
ocorrenciaRel.Ocorrencia = ocorrencia.NumOcorrencia;
ocorrenciaRel.Protocolo = ocorrencia.Protocolo;
ocorrenciaRel.Tipo = ocorrencia.Tipo?.Descricao;
ocorrenciaRel.Cliente = ocorrencia.EmpresaCliente.sigla.ToUpper();
ocorrenciaRel.UF = ocorrencia.EmpresaCliente.estado;
ocorrenciaRel.Grupo = ocorrencia.EmpresaCliente.nomeGrupo;
ocorrenciaRel.Representante = ocorrencia.EmpresaRepresentante.nomeFantasia.ToUpper();
ocorrenciaRel.Filial = ocorrencia.EmpresaFilial.sigla.ToUpper();
ocorrenciaRel.Km = ocorrencia.Deslocamento;
ocorrenciaRel.Motivo = ocorrencia.Motivo?.Descricao;
ocorrenciaRel.DataHoraAbertura = ocorrencia.DataHoraAbertura;
ocorrenciaRel.Equipamento = ocorrencia.NomeEquipamentoFocus;
ocorrenciaRel.Serie = ocorrencia.Serie;
ocorrenciaRel.DataHoraAgendada = ocorrencia.DataHoraAgendada;
ocorrenciaRel.DataHoraAtendimento = ocorrencia.DataHoraAtendimento;
ocorrenciaRel.DataHoraFechamento = ocorrencia.DataHoraFechamento;
ocorrenciaRel.Status = ocorrencia.Status?.Descricao;
ocorrenciaRel.Solucao = ocorrencia.Solucao?.Descricao;
ocorrenciaRel.Observacao = ocorrencia.Observacao;
ocorrenciaRel.Conclusao = ocorrencia.Conclusao?.Descricao;
ocorrenciaRel.OrdemServico = ocorrencia.OrdemServico;
ocorrenciaRel.Orcamento1 = ocorrencia.NumOrcamento;
ocorrenciaRel.Orcamento2 = ocorrencia.NumOrcamento2;
ocorrenciaRel.CedulasProcessadas = ocorrencia.CedulasProcessadas;
ocorrenciaRel.Tecnico = ocorrencia.OcorrenciaTecnico?.FirstOrDefault().Nome;
ocorrenciaRel.CobrarDeslocamento = ocorrencia.CobrarDeslocamento ? "Sim" : "Não";
ocorrenciaRel.CobrarAtendimento = ocorrencia.CobrarAtendimento ? "Sim" : "Não";

It is common to come across these problems and you can get around in different ways. Some have already given some suggestions in the other answers that prevent your code from breaking. Reinforcing that it is always important to check if a property is null before using it.

I usually, in some cases I know that there may be some problem in assigning the data already keep in the way I gave the above example. Because the shape that is in your code (depending on the class) becomes a disadvantage to debug and locate the problem in the code. So consider in your case what’s best.

In other cases, you can switch to the form I gave the example just to locate the problem and return to instantiation as before, if you think the code is safe and easy to understand (I do not find the most elegant, see below).

For your specific case I would choose to use a public static explict operator because you are basically making a conversion from one method to another that has very similar characteristics.

To simplify this example I will use smaller example classes:

Example class (Entity):

public class MinhaEntidade
{
    public long Id { get; set; }
    public string Prop1 { get; set; }
    public bool Prop2 { get; set; }
    public DateTime? Prop3 { get; set; }

    public static explicit operator MinhaEntidade(MinhaEntidadeDTO entidadeDTO)
    {
        return new MinhaEntidade
        {
            Id = entidadeDTO.Id,
            Prop1 = entidadeDTO.Prop1,
            Prop2 = entidadeDTO.Prop2,
            Prop3 = entidadeDTO.Prop3,
        };
    }
}

Example class (DTO):

public class MinhaEntidadeDTO
{
    public long Id { get; set; }
    public string Prop1 { get; set; }
    public bool Prop2 { get; set; }
    public DateTime? Prop3 { get; set; }
    //Propriedade não utilizada na conversão da classe. 
    //As classes não precisam ter as mesmas proprieades para utlização do explicit operator
    public DateTime? PropXYZ { get; set; }

    public static explicit operator MinhaEntidadeDTO(MinhaEntidade entidade)
    {
        return new MinhaEntidadeDTO
        {
            Id = entidade.Id,
            Prop1 = entidade.Prop1,
            Prop2 = entidade.Prop2,
            Prop3 = entidade.Prop3,
        };
    }
}

Converting from one entity to another would be so simple:

MinhaEntidadeDTO entidadeDTO = (MinhaEntidadeDTO )_db.MinhaEntidade
                                .Where(id == 1).SingleOrDefault();

The great advantage is no need to repeat the code to convert the object from one to the other whenever performing this operation. And you can change the method by validating the data with the tips I gave earlier and/or use the way I gave the first example in the method static explict operator facilitating the debugging.

Understand more about the explict reading the Microsoft documentation.

  • Yeah, I always end up doing it, but there’s no way I don’t have to do it?

  • @Taian, there are some other ways to instantiate the object yes, it can be a constructor where you can treat this data that can give some problem, a method, but in the end it will be something similar and I don’t think it will be easier for you. I will complement a little the answer giving some tips

  • @Taian, I updated the answer. I hope it helps you.

2

Not long ago I also had the same problem, the only solution I found was first instantiating and then set to the properties.

  • @Leandrade Why don’t you answer the question? he said the solution was instantiating, maybe he could have added example as George, but still responds

  • 2

    @Barbetta I removed the revision, but, for me since it did not exemplified with code, could very well be just a comment on the question.

  • @Barbetta Do you mean that in order for me to answer a question, I have to present lines of code? The way Taian made the quote is correct and I answered his question. Not necessarily by presenting code.

  • Augusto, actually it’s just a tip from @Barbetta ... We’re just presando for more complete and exemplified responses in the community. As he said himself, his position is still valid. :)

  • @Augustohenrique You had received a signage, I questioned the signage. Your answer is valid, it’s better with examples in code, but it’s still valid.

  • I understand @Barbetta, it is emphasized that I am recent in the community. I will learn, rs!

  • @Augustohenrique Welcome :D do not forget to do the [tour] and it is possible to follow the discussions on how the so-en Meta

  • Thanks, the Meta didn’t know it existed.

Show 3 more comments

1

You can use an auxiliary method to allow you to debug.

T BreakMe<T>(Func<T> func)
{
    Debugger.Break();
    return func();
}

I’d wear it like this:

var ocorrencias = _db.Ocorrencia.AsEnumerable().Select(ocorrencia => new OcorrenciaRelatorioDTO
{
    Id = BreakMe(() => ocorrencia.Id),
    Ocorrencia = BreakMe(() => ocorrencia.NumOcorrencia),

    //...

}).ToList();

0

Use a static method overload Isnotnull class Assert in namespace Microsoft.VisualStudio.Testtools.Unittesting.

The class Assert is a collection of auxiliary methods aimed at testing various conditions. If the condition being tested is not met, an exception will be made.

IsNotNull test if the specified object is non-null and throw an exception if it is null.

Assert.IsNotNull(ocorrencia.Id);
ocorrenciaRel.Id = ocorrencia.Id;
Assert.IsNotNull(ocorrencia.NumOcorrencia);
ocorrenciaRel.Ocorrencia = ocorrencia.NumOcorrencia;
Assert.IsNotNull(ocorrencia.Protocolo;
ocorrenciaRel.Protocolo = ocorrencia.Protocolo;
.
.
.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.