GraphDiff
库来更新断开连接的图。我的 Document
实体与 DocumentRelationShip
实体作为 ToDocumentRelationship
导航属性具有一对多关系。如果需要的话,我想自己删除 DocumentRelationships
,所以我用 UpdateGraph()
作为第三个参数来调用 false
方法。
对已保存的 UpdateGraph()
调用 Document
方法后,doc
及其 ToDocumentRelationship
条目状态为 Detached
。当我想使用以下代码删除 doc
关系之一时:
using (var ctx = new MyDbContext())
{
var doc = ctx.Documents
.Include(x => x.ToDocumentRelationShips)
.Where(x=>x.Id == 1234)
.AsNoTracking().FirstOrDefault();
...
ctx.UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationShips),
false);
...
var docRelation = doc.ToDocumentRelationShips().First();
if(someConditions)
{
// at this point ctx.Entry(docRelation).State is Detached
ctx.Entry(docRelation).State = EntityState.Deleted; //<- Exception raise at this point
}
ctx.SaveChanges();
}
我收到错误:
附加“DocumentRelationship”类型的实体失败,因为同一类型的另一个实体已具有相同的主键值。如果图表中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。
如何解决这个问题?
我快速浏览了这个 GraphDiff 源,看起来当它执行此操作时,它正在分别加载和跟踪实体到您在调用 UpdateGraph 时提供的分离实体。 UpdateGraph 返回对跟踪实体的引用。因此,在图表更新后删除实例所需要做的就是捕获跟踪的实体并在那里进行修改。由于文档关系实际上是文档的子级,因此我将通过文档的导航属性集合而不是实体状态来删除它们:
var trackedDocument = ctx.UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationShips),false);
...
var docRelation = trackedDocument.ToDocumentRelationShips().First();
if(someConditions)
{
trackedDocument.ToDocumentRelationships.Remove(docRelation);
}
ctx.SaveChanges();
这应该可以解决您的问题。尝试使用分离副本中的
.Entry(docRelation)
将会尝试将其附加到 UpdateGraph 已加载并跟踪实例的位置,从而导致异常。