Update generating duplicate key error

6

I have a web application in .net 4.5.1 with MVC and entity framework.

The error occurs in a basic CRUD.

I retrieve the object that will be the model sent to the view with the following code:

Professor professor = db.Pessoa
            .Include(p => p.Agenda)
            .Include(p => p.Contato)
            .Include(p => p.Endereco)
            .Include(p => p.SocioEconomico)
            .Include(p => p.SocioEconomico.TelefoneMae)
            .Include(p => p.SocioEconomico.TelefonePai)
            .Include(p => p.Contato.Telefones)
            .Where(p => p is Professor)
            .Single(p => p.Id == id.Value) as Professor;

This object is sent to the view and then I get the POST with the purpose of updating one or more fields.

In POST it has the following code:

            db.Entry(professor).State = EntityState.Modified;
            db.SaveChanges();

But when I pass the tem that changes the entity's status to "Modified" I get the following exception:

  

An object with the same key already exists in the ObjectStateManager. The ObjectStateManager can not track multiple objects with the same key.

If I retrieve the "Teacher" using the Find professor = db.Find(id) method, the update works correctly, but I do not have the "child" objects of it.

I have seen several possible solutions, but none worked. Has anyone had the same problem and can you tell me the error?

Adding all controller methods definition as required

GET

 public ActionResult Edit(int? id)
        {
            if (id == null)
            {
                return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
            }
            Professor professor = db.Pessoa
                .Include(p => p.Agenda)
                .Include(p => p.Contato)
                .Include(p => p.Endereco)
                .Include(p => p.SocioEconomico)
                .Include(p => p.SocioEconomico.TelefoneMae)
                .Include(p => p.SocioEconomico.TelefonePai)
                .Include(p => p.Contato.Telefones)
                .Where(p => p is Professor)
                .Single(p => p.Id == id.Value) as Professor;

            if (professor == null)
            {
                return HttpNotFound();
            }
            return View(professor);
        }

POST

public ActionResult Edit(Professor professor)
        {
            if (ModelState.IsValid)
            {
                db.Entry(professor).State = EntityState.Modified;

                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(professor);
        }
    
asked by anonymous 03.02.2014 / 22:15

3 answers

4

Check the Id of child objects, this is probably the problem. You will need to include a hidden field in the form for each child object id.

    
03.02.2014 / 23:17
7

This error means that you loaded the object professor twice (on different objects). During a method, you can only load the object once.

If you really need to load the object twice (for example, when you want to have the original values inside the same method), use:

Professor professorOriginal = db.Pessoa
        .AsNoTracking()
        .Include(p => p.Agenda)
        .Include(p => p.Contato)
        .Include(p => p.Endereco)
        .Include(p => p.SocioEconomico)
        .Include(p => p.SocioEconomico.TelefoneMae)
        .Include(p => p.SocioEconomico.TelefonePai)
        .Include(p => p.Contato.Telefones)
        .Where(p => p is Professor)
        .Single(p => p.Id == id.Value) as Professor;

A caveat: do not send this object loaded with AsNoTracking() to the context, or EntityFramework will try to save another object with a new ID in the database. AsNoTracking() indicates that you are loading the highlighted context object.

Addendum

Complementing the @uristone response, if child objects come via POST without the Ids, EntityFramework interprets the object coming from the form as an object other than the first. So the error.

    
03.02.2014 / 22:22
0

Check your database if there are not two records with the same ID and if the field is not auto-incrementing correctly.

    
03.02.2014 / 23:14