在实体框架中,您可以使用外键关联。也就是说,另一个对象的外键表示为两个属性对:原始外键属性(例如NominalRouting.OrderItemId
)和对象引用(NominalRouting.OrderItem
).
这意味着您可以设置原始值或对象引用来建立外键关联。如果您设置其中一项,EF 会在可能的情况下尝试使另一项保持同步。不幸的是,这也可能会引起原始外键值与其随附引用之间的冲突。
很难说清楚你的情况到底发生了什么。但是,我do知道您将对象从一个父级“复制”到另一个父级的方法......并不理想。首先,更改主键值从来都不是一个好主意。通过将它们设置为0
你让物体看起来像新的一样,但它们却不是。其次,您多次将相同的子对象分配给其他父对象。我think结果,您最终会得到大量具有外键的对象value但不是参考.
我说“复制”,因为这就是你似乎想要实现的目标。如果是这样,您应该正确克隆对象并Add
他们对每个targetOrderItem
。同时,我想知道为什么你(显然)克隆所有这些对象。看起来多对多关联在这里更合适。但那是另一个话题了。
现在你的实际问题是:如何找到冲突的关联?
这非常非常困难。它将需要代码来搜索概念模型并查找外键关联中涉及的属性。然后你必须找到他们的价值观并找到不匹配的地方。足够困难,但与确定何时possible冲突是一个actual冲突。让我通过两个例子来澄清这一点。这里,一堂课OrderItem
具有由属性组成的所需外键关联Order
and OrderId
.
var item = new OrderItem { OrderId = 1, ... };
db.OrderItems.Add(item);
db.SaveChanges();
所以有一个项目OrderId
分配和Order
= null,EF 很高兴。
var item = db.OrderItems.Include(x => x.Order).Find(10);
// returns an OrderItem with OrderId = 1
item.Order = null;
db.SaveChanges();
再次,一个项目OrderId
分配和Order
= null,但 EF 抛出异常“关系无法更改...”。
(而且可能发生冲突的情况也比较多)
所以仅仅寻找不匹配的值是不够的OrderId/Order
对,您还必须检查实体状态并确切地知道哪些状态组合不允许不匹配。我的建议:忘记它,修复你的代码。
不过,还有一个肮脏的伎俩。当 EF 尝试匹配外键值和引用时,在嵌套树深处的某个位置if
它将我们正在讨论的冲突收集到一个成员变量中ObjectStateManager
, named _entriesWithConceptualNulls
。可以通过一些反射来获得它的值:
#if DEBUG
db.ChangeTracker.DetectChanges(); // Force EF to match associations.
var objectContext = ((IObjectContextAdapter)db).ObjectContext;
var objectStateManager = objectContext.ObjectStateManager;
var fieldInfo = objectStateManager.GetType().GetField("_entriesWithConceptualNulls", BindingFlags.Instance | BindingFlags.NonPublic);
var conceptualNulls = fieldInfo.GetValue(objectStateManager);
#endif
conceptualNulls
is a HashSet<EntityEntry>
, EntityEntry
是一个内部类,因此您只能检查调试器中的集合以了解冲突的实体。仅用于诊断目的!