Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiplicity constraint violated. The role '...' of the relationship '...' has multiplicity 1 or 0..1

Tags:

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;      } 
like image 875
user1566694 Avatar asked Apr 08 '13 17:04

user1566694


2 Answers

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()); 
like image 160
user1566694 Avatar answered Oct 25 '22 18:10

user1566694


The problem is that detachedChild.parent should be assigned attachedParent.

foreach(var detachedEntity in detachedEntities) {      attachedEntity.ChildEntities.Add(detachedEntity);       detachedEntity.ParentEntity = attachedEntity; } 
like image 43
Arturo Hernandez Avatar answered Oct 25 '22 17:10

Arturo Hernandez