Saint
Saint

Reputation: 5469

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.

Upvotes: 0

Views: 564

Answers (2)

Eranga
Eranga

Reputation: 32447

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

Upvotes: 1

Brad Rem
Brad Rem

Reputation: 6026

I think your problem is your Except statement. It is comparing your collection items using the Default comparer which is comparing to see if the items reference the same object in memory when you actually intend it to compare the values of your Teacher objects.

The solution is to provide your own IEqualityComparer and specify exactly how the Teacher objects should be compared to each other. MSDN provides a good example of how to do this.

Upvotes: 0

Related Questions