You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GraphDiff删除Detached状态实体时触发DbContext异常如何解决?

问题原因

调用UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationships), false)时,GraphDiff会自动将doc及其关联的DocumentRelationship实体附加到EF上下文,并将它们的状态设为Unchanged。此时你再从doc.ToDocumentRelationships中取出实体尝试标记为Deleted,EF会尝试重新附加这个实例,但上下文已经存在同一主键的跟踪实体,因此抛出主键冲突异常。

解决方法

方法1:直接操作上下文已跟踪的实体

既然UpdateGraph已经把关联实体附加到上下文,直接从上下文的本地跟踪集合里获取目标实体再标记删除即可:

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 = ctx.DocumentRelationships.Local.FirstOrDefault(dr => dr.Id == 目标ID);
   // 也可以用Find方法,会优先查本地缓存
   // var docRelation = ctx.Find<DocumentRelationship>(目标ID);
   if(someConditions && docRelation != null)
   {           
       ctx.Entry(docRelation).State = EntityState.Deleted;
   }
   ctx.SaveChanges();
}

方法2:移除集合元素后开启自动删除

如果你的删除逻辑只是移除集合中的特定元素,可以先从doc.ToDocumentRelationships里删掉目标实体,再把UpdateGraph的第三个参数设为true,让GraphDiff自动处理删除操作:

using (var ctx = new MyDbContext())
{
   var doc = ctx.Documents
                .Include(x => x.ToDocumentRelationships)
                .Where(x=>x.Id == 1234)
                .AsNoTracking().FirstOrDefault();
   ... 
   var docRelation = doc.ToDocumentRelationships.First();
   if(someConditions)
   {           
       doc.ToDocumentRelationships.Remove(docRelation);
   }
   // 开启自动删除,GraphDiff会删除不在当前集合中的关联实体
   ctx.UpdateGraph(doc, opt => opt.OwnedCollection(x => x.ToDocumentRelationships), true);
   ctx.SaveChanges();
}

方法3:检查跟踪状态后再处理

如果必须从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)
   {           
       // 查找上下文已跟踪的对应实体
       var trackedEntry = ctx.ChangeTracker.Entries<DocumentRelationship>()
                           .FirstOrDefault(e => e.Entity.Id == docRelation.Id);
       if(trackedEntry != null)
       {
           trackedEntry.State = EntityState.Deleted;
       }
       else
       {
           ctx.Entry(docRelation).State = EntityState.Deleted;
       }
   }
   ctx.SaveChanges();
}

内容的提问来源于stack exchange,提问作者Masoud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 16:08:12