Reputation: 1196
We have an MVC project using Entity FrameWork where we have three tables, a class table, a student table and a teacher table. Teacher and student tables have relationship with class table by CLASS_ID. We are trying to make a copy of a class and insert it to database along with its teachers and students.
public void MakeClassCopy(int classID){
var copiedClass = database.TABLE_CLASS.Where(x => x.ID == classID).First();
var students = copiedClass.TABLE_STUDENTS.ToList(); //Lines that cause the exception
var teachers = copiedClass.TABLE_TEACHERS.ToList(); //Lines that cause the exception
database.TABLE_CLASS.Add(copiedClass);
database.SaveChanges();
string newTableID = copiedClass.ID;
//Insert students and teachers with new CLASS_ID here
}
This method works if we omit the problematic lines, but when executed like this, we get a runtime exception saying
"The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: A referential integrity constraint violation occurred: The property value(s) of 'TABLE_CLASS.ID' on one end of a relationship do not match the property value(s) of 'TABLE_STUDENTS.CLASS_ID' on the other end."
Why are we getting this error only by defining two variables? We don't even use them in any other code.
Upvotes: 2
Views: 1833
Reputation: 3702
By selecting the students and teachers of the 'copiedClass', you're actually selecting those of the class with class_id 'classId' into the database context. Those objects remain in memory.
Next you probably change the class_id of those objects, and insert them into the database. All is well until the insert is finished and the cache tries to update. This cache has a reference to all those fetched objects, but with different class_id's.
The students you fetched with the ToList, are now linked to another class and that's not consistent with the context.
When copying objects, you have 2 clean options:
1. create new objects, copy properties of the previous objects and insert them
OR
2. use the first context to fetch the objects, and a 2nd context to insert the new objects
Upvotes: 3