2

I am trying to duplicate an object in Entity Framework using the method in this answer, but when I call Add(clone) I get an InvalidOperationException saying that a multiplicity constraint has been violated. My code looks like this

var dbSet = context.Set<MyObject>()
var clone = dbSet.Include(e => e.Property1)
                 .Include(e => e.Property2)
                 .Include(e => e.Property3)
                 .AsNoTracking()
                 .First(e => e.Id == OriginalPrimaryKey)
dbSet.Add(clone); // Throws InvalidOperationException
context.SaveChanges();

The stack trace looks like

System.InvalidOperationException was unhandled by user code
HResult=-2146233079 Message=Multiplicity constraint violated. The role 'MyObject_Property1_Target' of the relationship 'DataModels.MyObject_Property1' has multiplicity 1 or 0..1. Source=EntityFramework StackTrace: at System.Data.Entity.Core.Objects.EntityEntry.WillNotRefSteal(EntityReference refToPrincipal, IEntityWrapper wrappedPrincipal) at System.Data.Entity.Core.Objects.EntityEntry.FixupEntityReferenceToPrincipal(EntityReference relatedEnd, EntityKey foreignKey, Boolean setIsLoaded, Boolean replaceExistingRef) at System.Data.Entity.Core.Objects.EntityEntry.FixupReferencesByForeignKeys(Boolean replaceAddedRefs, EntitySetBase restrictTo) at

Note that Property1 is a full object with a foreign key back to MyObject. From what I can tell, the multiplicity error is coming from the fact that the Property1 objects between an existing entity and my clone are "the same" according to EF (they are not reference equal, I checked).

From the looks of the above answer, I thought when using AsNoTracking EF would handle this and generate a new version of the Property1 entity to save to the database. Is this not the case? If not, what is the best way to clone my entire entity with all referenced properties?

Community
  • 1
  • 1
Kris Harper
  • 5,672
  • 8
  • 51
  • 96

1 Answers1

5

I fixed this by setting the primary keys of all referenced properties to 0. So my code now looks like

var dbSet = context.Set<MyObject>();
var clone = dbSet.Include(e => e.Property1)
                 .Include(e => e.Property2)
                 .Include(e => e.Property3)
                 .AsNoTracking()
                 .First(e => e.Id == OriginalPrimaryKey);
clone.Property1.Id = 0;
clone.Property2.Id = 0;
clone.Property3.Id = 0;
dbSet.Add(clone);
context.SaveChanges();

I'm not sure if this is the right way to do this—it certainly doesn't feel right—but I haven't been able to find anything else that works.

Kris Harper
  • 5,672
  • 8
  • 51
  • 96