Error updating data

2

I have a base repository where I only run CRUD. When working with one die at a time, it works normally. However, I needed to make a modification and send several records to be edited at once. But in doing so, I get an error.

When you click on the refresh button, it searches the data for Id , and reaches the Update method with all the data to update, including the ID. As can be seen in the image below:

However,whenIgettolineDbSet.Attach(obj);Igetthefollowingerror:

  

Attachinganentityoftype'PrestacaoWeb.Domain.Entities.Prestacao'failedbecauseanotherentityofthesametypealreadyhasthesameprimarykeyvalue.Thiscanhappenwhenusingthe'Attach'methodorsettingthestateofanentityto'Unchanged'or'Modified'ifanyentitiesinthegraphhaveconflictingkeyvalues.Thismaybebecausesomeentitiesarenewandhavenotreceiveddatabase-generatedkeyvalues.Inthiscaseusethe'Add'methodorthe'Added'entitystatetotrackthegraphandthensetthestateofnon-newentitiesto'Unchanged'or'Modified'asappropriate.

Lookingat this question I noticed that the problem is similar, but I did not understand the answer, and how to apply here.

My Entity looks like this:

public class Prestacao
    {
        public Prestacao()
        {
            PrestacaoId = Guid.NewGuid();
        }

        public Guid PrestacaoId { get; set; }
        public string Uf { get; set; }
        public string Municipio { get; set; }
        public string Orgao { get; set; }
        public string NomeEntidade { get; set; }
        public string TipoPrestacao { get; set; }
        public string Prazo { get; set; }
        public string Responsavel { get; set; }
        public string Telefone { get; set; }
        public string TipoPendencia { get; set; }
        public string Observacao { get; set; }
        public DateTime DataCadastro { get; set; }

        public Guid MesId { get; set; }

        public virtual Mes Mes{ get; set; }
    }

And my Controller, looks like this:

[HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Editar(List<PrestacaoViewModel> prestacaoViewModel)
        {
            if (ModelState.IsValid)
            {
                foreach (var item in prestacaoViewModel)
                {
                    if (item != null)
                    {
                        var prestacao =_prestacaoAppService.ObterPorId(item.PrestacaoId);

                        _prestacaoAppService.Atualizar(prestacao);
                    }
                }

                return RedirectToAction("Index");
            }

            return View("Index");
        }

Method of% generic%:

public void Update(TEntity obj)
        {
            var entry = Context.Entry(obj);
            DbSet.Attach(obj);
            entry.State = EntityState.Modified;
        }
    
asked by anonymous 12.05.2015 / 17:00

3 answers

2

This can not be done here:

DbSet.Attach(obj);
entry.State = EntityState.Modified;

Or you modify the State of entry , or you do a Attach ". The recommended is the first, that is:

public void Update(TEntity obj)
{
    var entry = Context.Entry(obj);
    entry.State = EntityState.Modified;
    Context.SaveChanges();
}

For the umpteenth time I will reiterate: do not use service layer . There is no need to separate an MVC application, where Controller already implements the role of a service . >

This here selects the registry twice:

if (item != null)
{
    var prestacao =_prestacaoAppService.ObterPorId(item.PrestacaoId);
    _prestacaoAppService.Atualizar(prestacao);
}

Do this:

if (item != null)
{
    _prestacaoAppService.Atualizar(prestacao);
}
    
12.05.2015 / 17:39
0

If you select the registry and try to do the update will generate the error because this entity will be attached in the DbSet evai give duplicate key error.

var prestacao =_prestacaoAppService.ObterPorId(item.PrestacaoId);
_prestacaoAppService.Atualizar(prestacao);

For this error to occur you will only have to send the viewmodel item without getting the entity again

foreach (var item in prestacaoViewModel)
{
     if (item != null)
     {
         _prestacaoAppService.Atualizar(item);
     }
}

If you need to verify that the registration is registered you can override its generic method in your repository in order to detach the entity from DbSet.

public override Prestacao Update(Prestacao prestacao)
{
      // primeiro encontra a entidade para atualizar
      var oldEntity = DbSet.Find(prestacao.PrestacaoId);
     // desanexar esta entidade do DbSet
      Db.Entry(oldEntity).State = EntityState.Detached;

      var entry = Db.Entry(prestacao);
      DbSet.Attach(prestacao);
      entry.State = EntityState.Modified;
      return prestacao;
}
    
09.04.2018 / 19:23
0

Making context using that context is created only inside the keys. This error occurs because there is a conflict of primary keys, instituting a context within the method you will open and close the connection with the bank within the same method avoiding this conflict.

using (var context = new Context ()) {

            contexto.Entry(produto).State = EntityState.Modified;
            contexto.SaveChanges();
 }
    
10.04.2018 / 00:23