Reputation: 5469
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
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
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