Error while updating data

Asked

Viewed 757 times

2

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

By clicking the refresh button, it looks for the data by Id, and arrives at the method of Update with all the data to update, including the Id. As can be seen in the image below:

Método update

But when you get to the line DbSet.Attach(obj); i get the following error:

Attaching an Entity of type 'Prestacaoweb.domain.Entities.Prestacao' failed because Another Entity of the same type already has the same Primary key value. This can happen when using the 'Attach' method or Setting the state of an Entity to 'Unchanged' or 'Modified' if any entities in the Graph have Conflicting key values. This may be because some entities are new and have not yet Received database-generated key values. In this case use the 'Add' method or the 'Added' Entity state to track the Graph and then set the state of non-new entities to 'Unchanged' or 'Modified' as appropriate.

Gazing this question I noticed that the problem is similar, but I didn’t understand the answer, and how to apply here.

My Entity is 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, it’s 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 Update generic:

public void Update(TEntity obj)
        {
            var entry = Context.Entry(obj);
            DbSet.Attach(obj);
            entry.State = EntityState.Modified;
        }
  • In var entry = Context.Entry(obj), there’s some code under the inspector’s box?

  • @Ciganomorrisonmendez does not have. I added the full code in the question, I had forgotten it.

3 answers

2


This can’t be here:

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

Or you modify the State of entry, or you make a Attach. The recommended is the first, ie:

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 into layer service an MVC application, where the Controller already implements the function of a service.

This here selects the record twice:

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

Do so:

if (item != null)
{
    _prestacaoAppService.Atualizar(prestacao);
}
  • I tried without using Attach. However I get the same error.

  • @Randrade I updated the answer.

  • I didn’t understand it very well. You withdrew the var rendericao, and update it below?

  • context.Entry(obj) already locates an object within a context (optimistically speaking). If you want the personal approach, you need to drop the pattern service: select the record, modify the property property, mark as changed and call the context to save.

0

Doing context using that context is only created within the keys. This error occurs because there is a primary key conflict, setting a context within the method you will open and close the connection to the bank within the same method avoiding this conflict.

using (var context = new Context()) {

            contexto.Entry(produto).State = EntityState.Modified;
            contexto.SaveChanges();
 }

0

If you select the record and try to update it will generate error as this entity will be attached in Dbset evai give duplicate key error.

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

for this error not to occur you will have to send only the viewmodel item without retrieving the entity

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

If you need to check if the registry is registered you can overwrite your generic method in your repository to be able to detach the Dbset entity.

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;
}

Browser other questions tagged

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