Instance of a certain type cannot be traced because another instance with the same key value for {'ID'} is already being tracked

Asked

Viewed 35 times

0

I am trying to update an entity of mine in the bank but without success, I visualized other posts of the subject, and their solution seems not to be serving for me.

I am using Entity Framework Core Version 5.0.9

In my role of the repository

public void Editar(Pessoa obj)
    {
        try
        {
            _context.Entry(obj).State = EntityState.Modified;

            _context.SaveChanges();
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }

I’ve tried to use _context.Attach(obj); but breaks the error on that same line of code

I’ve tried to use _context.Update(obj); but also bursts the same error

I’ve tried to use _context.Entry(obj).State = EntityState.Detached;, along with the _context.SaveChanges();, but my object in the bank is not changed

Bug name

The instance of Entity type 'Pessoa' cannot be tracked because Another instance with the same key value for {'Codigocliente'} is already being tracked. When Attaching existing entities, ensure that only one Entity instance with a Given key value is Attached. Consider using 'Dbcontextoptionsbuilder.Enablesensitivedatalogging' to see the Conflicting key values.

Search, Delete and Create methods work normally

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }

    public virtual DbSet<Pessoa> Pessoa { get; set; }
    public virtual DbSet<Licenca> Licenca { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //modelBuilder.Entity<PessoaConfig>();
        //modelBuilder.Entity<LicencaConfig>();

        modelBuilder.ApplyConfiguration(new PessoaConfig());
        modelBuilder.ApplyConfiguration(new LicencaConfig());


        base.OnModelCreating(modelBuilder);
    }
}


public class PessoaConfig : IEntityTypeConfiguration<Pessoa>
{
    public void Configure(EntityTypeBuilder<Pessoa> builder)
    {
        builder.ToTable("Cliente");

        builder.HasKey(x => x.CodigoCliente);

        builder.Property(x => x.CodigoCliente).HasColumnName("cd_cliente");
        builder.Property(x => x.TipoPessoa).HasColumnName("tp_pessoa");
        builder.Property(x => x.Advogado).HasColumnName("fl_advogado");
        builder.Property(x => x.Captador).HasColumnName("fl_captador");
        builder.Property(x => x.Cobrador).HasColumnName("fl_cobrador");
        builder.Property(x => x.Cliente).HasColumnName("fl_cliente");
        builder.Property(x => x.Fornecedor).HasColumnName("fl_fornecedor");
        builder.Property(x => x.Devedor).HasColumnName("fl_devedor");
        builder.Property(x => x.Nome).HasColumnName("no_cliente");
        builder.Property(x => x.InscricaoEstadual).HasColumnName("nr_ie");
        builder.Property(x => x.InscricaoMunicipal).HasColumnName("nr_im");
        builder.Property(x => x.Rg).HasColumnName("nr_ci");
        builder.Property(x => x.Login).HasColumnName("cd_usuario");
        builder.Property(x => x.TipoAdvogado).HasColumnName("tp_advogado");
        builder.Property(x => x.Observacao).HasColumnName("de_observacao");
        builder.Property(x => x.GrupoSeguranca).HasColumnName("cd_grupo");
        builder.Property(x => x.Atividade).HasColumnName("cd_atividade");
        builder.Property(x => x.Contato).HasColumnName("fl_contato");
        builder.Property(x => x.Oficial).HasColumnName("fl_oficiais");
        builder.Property(x => x.Segurado).HasColumnName("fl_segurados");
        builder.Property(x => x.GrupoCliente).HasColumnName("cd_grupo_cliente");
        builder.Property(x => x.Autor).HasColumnName("fl_autor");
        builder.Property(x => x.Reu).HasColumnName("fl_reu");
        builder.Property(x => x.CodigoAlteracao).HasColumnName("cd_alteracao");
        builder.Property(x => x.DataAlteracao).HasColumnName("dt_alteracao");
        builder.Property(x => x.CodigoCriacao).HasColumnName("cd_criacao");
        builder.Property(x => x.DataCriacao).HasColumnName("dt_criacao");
        builder.Property(x => x.Filial).HasColumnName("cd_filial_cliente");
        builder.Property(x => x.Inativo).HasColumnName("fl_inativo");
        builder.Property(x => x.Localizador).HasColumnName("fl_localizador");
        builder.Property(x => x.Usuario).HasColumnName("fl_usuario");
        builder.Property(x => x.Filiais).HasColumnName("cd_filialss");
        builder.Property(x => x.Nascimento).HasColumnName("dt_nascimento");
        builder.Property(x => x.Setor).HasColumnName("cd_setor");
        builder.Property(x => x.Amigavel).HasColumnName("fl_amigavel");
        builder.Property(x => x.Juridico).HasColumnName("fl_juridico");
        builder.Property(x => x.Horario).HasColumnName("cd_horario");
        builder.Property(x => x.Admissao).HasColumnName("dt_admissao");
        builder.Property(x => x.Rescisao).HasColumnName("dt_rescisao");
        builder.Property(x => x.Banco).HasColumnName("cd_banco");
        builder.Property(x => x.Agencia).HasColumnName("nr_agencia");
        builder.Property(x => x.Conta).HasColumnName("nr_conta");
        builder.Property(x => x.Cartorio).HasColumnName("fl_cartorio");
        builder.Property(x => x.Admissao2).HasColumnName("dt_admissao2");
        builder.Property(x => x.Rescisao2).HasColumnName("dt_rescisao2");
        builder.Property(x => x.GrupoCobranca).HasColumnName("cd_grupo_cobranca");
        builder.Property(x => x.DigitoConta).HasColumnName("cd_dv");
        builder.Property(x => x.Cpf).HasColumnName("nr_cpf");
        builder.Property(x => x.Cnpj).HasColumnName("nr_cgc");
        builder.Property(x => x.ArquivoMorto).HasColumnName("de_morto");
        builder.Property(x => x.Cargo).HasColumnName("cd_cargo");
        builder.Property(x => x.Ramal).HasColumnName("nr_ramal_cob");
        builder.Property(x => x.Empresa).HasColumnName("cd_empresa");
        builder.Property(x => x.Email).HasColumnName("de_mail");
        builder.Property(x => x.ValidaHorario).HasColumnName("fl_valida_horario");
        builder.Property(x => x.PosJuridico).HasColumnName("fl_pos_juridico");
        builder.Property(x => x.Oab).HasColumnName("nr_inscricao_oab");
        builder.Property(x => x.CarteiraFoco).HasColumnName("fl_foco");
        builder.Property(x => x.DigitoAgencia).HasColumnName("cd_dv_agencia");
        builder.Property(x => x.OpVar).HasColumnName("cd_op_var");
        builder.Property(x => x.Pis).HasColumnName("nr_pis");
        builder.Property(x => x.UtilizaSoftPhone).HasColumnName("fl_discador");
        builder.Property(x => x.CarteiraWo).HasColumnName("fl_wo");
        builder.Property(x => x.Senha).HasColumnName("id_password");
        builder.Property(x => x.TipoCentral).HasColumnName("fl_tipo_central");
        builder.Property(x => x.DiscagemManual).HasColumnName("fl_manual");
        builder.Property(x => x.CentralAlternativa).HasColumnName("fl_alternativa");
        builder.Property(x => x.Receptivo).HasColumnName("fl_receptivo");
        builder.Property(x => x.MetaDiscador).HasColumnName("fl_meta_discador");
        builder.Property(x => x.SapClienteNcNds).HasColumnName("cd_cliente_sap_nc");
        builder.Property(x => x.SapClienteNrp).HasColumnName("cd_cliente_sap_nrp");
        builder.Property(x => x.SapFornecedorNds).HasColumnName("cd_cliente_sap");
        builder.Property(x => x.EmailFuncional).HasColumnName("cd_contato_se");
        builder.Property(x => x.TipoUsuario).HasColumnName("fl_tipo_usuario");
        builder.Property(x => x.Fiador).HasColumnName("fl_fiador");
        builder.Property(x => x.SegurancaGrupoCobranca).HasColumnName("cd_seg_grupo_cobranca");
    }

If you need more information to find out the error you may ask

3 answers

1


Try inserting the following into your context constructor:

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
            ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
            ChangeTracker.AutoDetectChangesEnabled = false;
    }
  • Thanks for the help Ari, could you give a brief explanation of what these changes you suggested mean ? and what it might impact on my system

0

I would modify your editing method to Asynchronous first and do some testing:

public async Task Editar(Pessoa p)
{
    //Faria o Track da entidade a partir de uma busca
    var pessoa = await _context.Pessoa.FindAsync(p.Id);
    
    //Faria a alterações
    pessoa.Nome = "Fulano";
    _context.Pessoa.Update(pessoa);
    await _context.SaveChangesAsync();
}

Take the test and see what.

Edit 1:

Based on your answer let’s try it this way:

Your Controller that receives JSON and has the repository injected with update method:

    [HttpPut("{id}")]
    [ProducesResponseType(StatusCodes.Status204NoContent)]
    [ProducesResponseType(StatusCodes.Status400BadRequest)]
    [ProducesResponseType(StatusCodes.Status500InternalServerError)]
    public async Task<IActionResult> Update(Guid id, [FromBody] PessoaDTO pessoaDTO)
    {
        try
        {               
            if (id == Guid.Empty || authorDTO == null || id != authorDTO.Id)
            {
                return BadRequest();
            }
            if (!ModelState.IsValid)
            {
                return BadRequest(ModelState);
            }
            var pessoa = _mapper.Map<Pessoa>(pessoaDTO);
            var isSuccess = await _pessoaRepository.Update(pessoa);
            if (!isSuccess)
            {
                return BadRequest();
            }
            return NoContent();
        }
        catch (Exception e)
        {
            return BadRequest();
        }
    }

Your repository in turn using the context to execute the changes:

    public async Task<bool> Update(Pessoa entity)
    {
        _context.Pessoas.Update(entity);
        return await Save();
    }
  • The way you suggested it works, but the way I’m trying to do it is different, I’ll explain the steps until I get to the repository method... 1 - I get this data via Json. 2 - Use Automapper to map all properties to the Person class. 3 - I search by ID what I received via JSON. and stored in a variable 4 - Assign the mapped object to that variable. 5 - Uploaded all this modified object to the Edit Repository method.... Is it possible to do this? because the way you indicated it made it hard to give scalability to that.

  • Try the dit I made

0

Tracking (Tracking) happens whenever you make a database query by one or more entities. Tracking helps the Entity framework realize the change of an object before it goes into the database. It fires a OnChangeNotification and save this in the EF Context properties. You can see the detail of this behavior here.

Tracking has its disadvantage, it also directly reaches the peformance of your code, because the EF will have to observe the modifications of the properties of the objects until it is saved in DB. But without it, you will lose the great advantage of EF of executing all changes of a Dbcontext in a single transaction.

It is possible to disable the tracker directly in Dbcontext, but I do not recommend if your application makes many changes in the database.

My recommendation: When doing a query using EF, consider whether you will need to tracker every modification of the object before going to the database. The vast majority of the times you use .ToList() and return the object for an API for example, you don’t need to use the EF trackers, in this case, use [YourEFQuery].AsNoTracking().ToList() (if you have not modified the tracker in Dbcontext).

In General, when you receive the data using a .Find() based on a ID this will come with tracker enabled, and it makes sense that it is so, after all you are wanting a single entity to make modifications.

Browser other questions tagged

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