I'm getting the following error from my DbContext: "Multiplicity constraint violated. The role 'MyEntity' of the relationship 'MyModel.FK_ChildEntities_MyEntities' has multiplicity 1 or 0..1."
using ASP.NET, Entity Framework 4
Working with a detached entity
The error happens the second time I try to reattach an entity to the dbcontext. The scenario is an unsuccessful save followed by a reattempt.
I have a detached entity in session. The user changes properties in a form, add things, removes things and finally clicks save. I get an attached copy of the entity from a new instance of the dbcontext, apply changes from the detached entity to the attached entity, validate, find an error and abort. The user changes whatever and saves again.
On the second save, the whole save process repeats, only this time it all goes to hell. Pretty much everything is duplicated, causing one error or another or all of them. Values from views and lookup tables that are only supposed to be references are created new and reassigned id's. Most of those issues I've been able to resolve, but I'm left with the multiplicity error. Child elements are being created as exact copies of other child elements, down to the unique id, only in the Added state. Or, if I reference certain properties, instead of cloning an unmodified child, it drops the new one. Either way, none of the code is executing as it did the first time around.
I'm discarding the instance of the dbcontext and the attached entity each save attempt. I thought that would be enough to revert any changes but something must be sticking around. The only thing not discared or reset is the detached entity, which is in session, but I dont make any changes to it. At least not directly.
The code (very simplified) is something like this:
void Save() { using (var context = new MyContext()) { // detached entity from session MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; // attached entity from context MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id); // <remove children representing lookup table elements from detachedEntity to prevent duplicates> // <remove children representing view elements from detachedEntity to prevent duplicates> // <apply changes from detachedEntity to attachedEntity> // <add new children> // <remove deleted children> // <update modified children> // <set entity state to unchanged on view and lookup elements of attachedEntity to ensure no duplicates...> // <validate> if (errors.count>0) // <report errors> else context.SaveChanges(); } }
as an example, this generates a multiplicity error:
// represents first save: using (var context = new MyContext()) { // detached entity from session MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; // attached entity from context MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id); int debug1 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug1 == 0; attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First()); int debug2 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug2 == 1; } // represents second save: using (var context = new MyContext()) { // detached entity from session MyEntity detachedEntity = (MyEntity)Session["DetachedEntity"]; // attached entity from context MyEntity attachedEntity = context.MyEntities.Single(x=>x.id == detachedEntity.id); int debug1 = context.ChangeTracker.Entries<ChildEntity>().Count(); // debug1 == 0; attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First()); int debug2 = context.ChangeTracker.Entries<ChildEntity>().Count(); // multiplicity error; }
somehow the dbcontext remembers what objects were added to it. if the exact same object shows up twice, it... blows
instead of adding child entities from my detached entity to the attached one, i should've been creating new copies of each child
ChildEntity detachedChild = detachedEntity.ChildEntities.First(); attachedEntity.ChildEntities.Add(new ChildEntity { propertyA = detachedChild.propertyA, propertyB = detachedChild.propertyB });
instead of
attachedEntity.ChildEntities.Add(detachedEntity.ChildEntities.First());
The problem is that detachedChild.parent should be assigned attachedParent.
foreach(var detachedEntity in detachedEntities) { attachedEntity.ChildEntities.Add(detachedEntity); detachedEntity.ParentEntity = attachedEntity; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With