EF Core InMemoryDatabase添加关联产品订单时实体跟踪异常求助
问题分析
你遇到的InvalidOperationException是因为EF Core的实体跟踪机制冲突:当调用_dbContext.Pedido.Add(pedido)时,EF会自动递归标记所有关联的Produtos实例为Added状态,但Id=1的Produtos已经存在于InMemory数据库中,且当前DbContext已经在跟踪该实体的另一个实例,导致同一Key的两个实例被同时跟踪,触发异常。
这种情况通常发生在:
- 请求传入的
Produtos是从JSON绑定生成的新实例,但该Id对应的产品已存在于数据库 - DbContext生命周期过长,之前的查询操作已经跟踪了该产品实例
解决方案
方案1:关联已存在的产品实例(推荐)
订单关联的产品应为数据库中已存在的实体,因此需要将请求中的产品替换为DbContext中已跟踪的实例,确保EF只处理同一个实例:
public Pedidos Adicionar(Pedidos pedido) { // 替换订单中的产品为数据库中已存在的实例 for (int i = 0; i < pedido.ProdutosPedido.Count; i++) { var produto = pedido.ProdutosPedido[i]; var existingProduto = _dbContext.Produto.Find(produto.Id); if (existingProduto != null) { pedido.ProdutosPedido[i] = existingProduto; } // 若产品不存在,可根据业务需求选择添加新产品或抛出异常 // else _dbContext.Produto.Add(produto); } _dbContext.Pedido.Add(pedido); _dbContext.SaveChanges(); return pedido; }
方案2:手动设置产品实体状态
如果确认产品已存在,可手动将关联的产品标记为Unchanged,告诉EF不需要修改或添加这些产品:
public Pedidos Adicionar(Pedidos pedido) { _dbContext.Pedido.Add(pedido); // 标记所有关联产品为已存在状态 foreach (var produto in pedido.ProdutosPedido) { _dbContext.Entry(produto).State = EntityState.Unchanged; } _dbContext.SaveChanges(); return pedido; }
方案3:修正实体关系配置
确保EF正确识别Pedidos与Produtos的多对多关系,避免自动添加重复实体:
在EFDBContext中添加关系配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置订单与产品的多对多关系 modelBuilder.Entity<Pedidos>() .HasMany(p => p.ProdutosPedido) .WithMany(); // 若Produtos中有反向导航属性,可改为.WithMany(prod => prod.Pedidos) }
方案4:检查DbContext生命周期
确保DbContext使用短生命周期(比如ASP.NET Core中的Scoped模式),避免长时间持有导致旧的跟踪实例未释放。
内容的提问来源于stack exchange,提问作者AgnesJes
相关产品推荐
相关产品推荐

