尝试克隆 Entity Framework 对象时违反了多重约束
Multiplicity constraint violated when trying to clone Entity Framework object
我正在尝试使用 this answer 中的方法复制 Entity Framework 中的一个对象,但是当我调用 Add(clone)
时,我得到一个 InvalidOperationException 说违反了多重性约束。我的代码看起来像这样
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();
堆栈跟踪看起来像
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
请注意 Property1
是一个完整的对象,外键返回 MyObject
。据我所知,多重性错误来自于这样一个事实,即根据 EF,现有实体和我的克隆之间的 Property1
对象是 "the same"(我检查过,它们的引用不相等)。
从上面的答案来看,我认为在使用 AsNoTracking
时 EF 会处理这个问题并生成一个新版本的 Property1
实体以保存到数据库中。不是这样吗?如果没有,克隆具有所有引用属性的整个实体的最佳方法是什么?
我通过将所有引用属性的主键设置为 0 来解决这个问题。所以我的代码现在看起来像
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();
我不确定这是否是正确的方法——它肯定感觉不对——但我还没有找到任何其他有效的方法。
我正在尝试使用 this answer 中的方法复制 Entity Framework 中的一个对象,但是当我调用 Add(clone)
时,我得到一个 InvalidOperationException 说违反了多重性约束。我的代码看起来像这样
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();
堆栈跟踪看起来像
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
请注意 Property1
是一个完整的对象,外键返回 MyObject
。据我所知,多重性错误来自于这样一个事实,即根据 EF,现有实体和我的克隆之间的 Property1
对象是 "the same"(我检查过,它们的引用不相等)。
从上面的答案来看,我认为在使用 AsNoTracking
时 EF 会处理这个问题并生成一个新版本的 Property1
实体以保存到数据库中。不是这样吗?如果没有,克隆具有所有引用属性的整个实体的最佳方法是什么?
我通过将所有引用属性的主键设置为 0 来解决这个问题。所以我的代码现在看起来像
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();
我不确定这是否是正确的方法——它肯定感觉不对——但我还没有找到任何其他有效的方法。