Update generating duplicate key error

Asked

Viewed 1,774 times

7

I have a web application on . net 4.5.1 with MVC and Entity framework.

Error occurs in a basic CRUD.

I recover 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 receive the POST in order to update one or more fields.

In the POST you have the following code:

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

But when going through the had 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 cannot track Multiple Objects with the same key.

If I retrieve the "Teacher" using the Find method professor = db.Find(id), update works properly, but I don’t have the "kids" objects from it.

I’ve seen several possible solutions, but none worked. Someone has had the same problem and can tell me which error?


Adding all controller method definitions as requested

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);
        }
  • 1

    Try this: db.Professores.Attach(Entity); db. Entry(Entity). State = Entitystate.Modified; //where we assume q Teachers contain your db.Set<Teacher>

  • iuristona, had already seen this possible solution. I even tried again here, but the error that occurs is the same. Now on the line where I do "Attach".

  • This is very suspicious: .Where(p => p is Professor).Single(p => p.Id == id.Value) as Professor. Try trading for .SingleOrDefault(p => p is Professor && p.Id == id.Value).

  • It is strange because the error occurs basically if you already have a Teacher object with the same key, in Objectstatemanager. Apparently you don’t, an alternative to trying to debug would be to inspect if you find a Teacher in db.Professores.Local.Firstordefault(m => m.Id == teacher.Id); The Local object contains the entities found in the Statemanager

  • Gypsy, what’s the difference? EF will interpret the two codes in the same way. It will only save one line. iuristona, really, in theory should only have one Teacher object in the Objectstatemanager. I will try this code and already put the result.

  • iuristona, the code returned null as expected. =/

  • I was very intrigued about what is causing the problem. Another attempt I would make, to detect if the problem is only with Teacher or with the children objects, would be to force a Clear in Objectstatemanager Professor: db.Professores.Local.Clear(); if the problem continues there is probably a duplicity in the Teacher’s children objects and this error is triggered when you attack Teacher and his children.

  • 1

    Another tip, q has nothing to do with the problem, is in the query. It would be more semantic you change to: db.Pessoa&#xA;.OfType<Professor>()&#xA; .Include(p => p.Agenda)&#xA; .Include(p => p.Contato)&#xA; .Include(p => p.Endereco)&#xA; .Include(p => p.SocioEconomico)&#xA; .Include(p => p.SocioEconomico.TelefoneMae)&#xA; .Include(p => p.SocioEconomico.TelefonePai)&#xA; .Include(p => p.Contato.Telefones)&#xA; .Where(p => p.Id == id.Value)&#xA; .FirstOrDefault()

  • It really gets more elegant and I avoid the "The Teacher". But back to the error... the ids of the children objects are zeroed. Could this be the mistake? If I’m changing, they should be with their respective ids, correct?

  • I’ll promote my comment as a response suggestion, okay?

  • Maybe you created partial class with the same namespace. .

Show 6 more comments

3 answers

8

This error means 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 within 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: nay send this object loaded with AsNoTracking() for context, or Entityframework will try to save another object with a new Id in the database. AsNoTracking() indicates that you are loading the highlighted object from the context.


Addendum

Complementing the answer of @iuristona, if the children objects come via POST without the Ids, the Entityframework interprets the object coming from the form as an object other than the first one. Hence the error.

5


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

  • 1

    It really was the most coherent response so far. But hunger doesn’t let me take that test at the moment. hehehe .

0

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

  • The id field is a primary key in the database and Identity. There can be no two records with the same id and no error in auto-increment.

Browser other questions tagged

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