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

EF Core出现同Id实体已被跟踪错误的核心触发原因是什么?

错误核心触发逻辑

EF Core的DbContext实例内部维护了一个跟踪实体缓存池,该设计是为了避免同一个主键对应两个不同的实体状态,导致后续提交数据库时出现数据冲突。每次执行实体关联操作(查询、Add、Attach、Update、Remove等)时,都会执行如下校验逻辑:

  1. 提取待操作实体的类型和主键值
  2. 检查当前缓存池中是否已经存在同类型、同主键值的被跟踪实例
  3. 如果存在,且待操作的实体和已跟踪实例不是同一个内存引用,就会抛出该错误。
触发错误的三个必要条件
  • 操作在同一个DbContext实例的生命周期内执行
  • 两次关联到DbContext的实体属于相同类型,且主键(该报错中为Id)取值完全一致
  • 第二次提交的实体是全新的内存对象,和已缓存的跟踪实例没有相同的引用地址
复现代码示例

首先定义基础实体和数据库上下文:

// 业务实体
public class Goods
{
    public int Id { get; set; }
    public string Title { get; set; }
    public decimal Price { get; set; }
}

// 数据库上下文
public class ShopDbContext : DbContext
{
    public DbSet<Goods> Goods { get; set; }
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer("数据库连接字符串");
    }
}

触发错误的代码:

using var db = new ShopDbContext();
// 第一步:查询Id=1的商品,此时该实例已被加入跟踪缓存
var existGoods = db.Goods.First(g => g.Id == 1);

// 第二步:手动构造一个Id同为1的新实例,和existGoods是不同的内存对象
var updateGoods = new Goods
{
    Id = 1,
    Title = "修改后的商品名",
    Price = 99.9
};

// 第三步:尝试将新实例加入跟踪,触发校验报错
db.Goods.Update(updateGoods);
db.SaveChanges();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 01:36:03