Search code examples
c#entity-frameworklinq-to-entitiesmany-to-manyobjectcontext

New object, but error: an object with the same key already exists in the objectstatemanager. the objectstatemanager cannot track multiple (...)


Student and Teacher are i relationship many-to-many.

When I have Student existed in database, and want to add new Teacher, I try code below.

But in line: addedTeachers.ForEach(a => dbStudent.Teacher.Add(a)); I get error

"an object with the same key already exists in the objectstatemanager. the objectstatemanager cannot track multiple objects with the same key".

What's wrong?

void Update(Student s)
{
    using(var context = new MyEntities(connectionString))
    {
        context.ContextOptions.LazyLoadingEnabled = false;
        var dbStudent = context.Student.Include("Teacher").Where(a => a.Id == s.Id).SingleOrDefault();

        var dbTeachers = dbStudent.Teacher.ToList();
        var newTeachers = s.Teacher.ToList();

        var addedTeachers = newTeachers.Except(dbTeachers).ToList();
        var deletedTeachers = dbTeachers.Except(newTeachers).ToList();

        addedTeachers.ForEach(a => dbStudent.Teacher.Add(a));
        deletedTeachers.ForEach(a => dbStudent.Teacher.Remove(a));

        context.SaveChanges();
    }
}

EDIT

What's strange else:

just before this line with exception dbStudent.Teacher.Count is 0. But after exception is 1. Of course addedTeachers.Count is also 1, but debugger doesn't reach the next line.


Solution

  • The problem is s and dbStudent has the same primary key. Your Teacher instances in s.Teacher collection may refer to the s instance. Then when you call addedTeachers.ForEach(a => dbStudent.Teacher.Add(a));, EF will identity all objects linked to teacher instance and try to add them too.

    Try

    addedTeachers.ForEach(a => { a.Students.Remove(s);
                                 a.Students.Add(dbStudent);
                                 dbStudent.Teacher.Add(a);});