首页 文章

无法跟踪实体类型'Item'的实例,因为已经跟踪了具有{'Id'}相同键值的另一个实例

提问于
浏览
3

我知道这个问题已经被提出,但解决方案对我没有帮助 .

[Fact]
public async Task UpdateAsync()
{
    string newTitle = "newTitle1";
    int newBrandId = 3;
    var item = await storeContext.Items.AsNoTracking().FirstOrDefaultAsync();
    item.BrandId = newBrandId;
    item.Title = newTitle;
    storeContext.Entry(item).State = EntityState.Detached;
    await service.UpdateAsync(item); // exception inside
    var updatedItem = await storeContext.Items.AsNoTracking().FirstOrDefaultAsync();
    Assert.Equal(newTitle, updatedItem.Title);
    Assert.Equal(newBrandId, updatedItem.BrandId);
}

public async Task UpdateAsync(T entity)
{
    _dbContext.Entry(entity).State = EntityState.Modified; // exception when trying to change the state
    await _dbContext.SaveChangesAsync();
}

消息:System.InvalidOperationException:无法跟踪实体类型“Item”的实例,因为已经跟踪了另一个具有{'Id'}键值的实例 . 附加现有实体时,请确保仅附加具有给定键值的一个实体实例 . 考虑使用'DbContextOptionsBuilder.EnableSensitiveDataLogging'来查看冲突的键值 .

有趣的是,即使没有从db中检索项目,异常也是一样的,就像这样

//var item = await storeContext.Items.AsNoTracking().FirstOrDefaultAsync();
  var item = new Item()
  {
      Id = 1,
      BrandId = newBrandId,
      CategoryId = 1,
      MeasurementUnitId = 1,
      StoreId = 1,
      Title = newTitle
  };

1 回答

  • 3

    我遇到过的许多问题都有一个令人讨厌的根源 . 简而言之:我已经学会了为什么dbContext是作用域而不是单例的困难方法 . 这是商店类型,但问题是相同的 . 这是简化的测试初始化代码

    public TestBase()
    {
        services = new ServiceCollection();
        storeContext = StoreContextMock.ConfigureStoreContext(services, output);
        serviceProvider = services.BuildServiceProvider();
    }
    public static StoreContext ConfigureStoreContext(IServiceCollection services)
    {
        services.AddDbContext<StoreContext>(c =>
            c.UseInMemoryDatabase(Guid.NewGuid().ToString()).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
    
        var serviceProvider = services.BuildServiceProvider();
        var storeContext = serviceProvider.GetRequiredService<StoreContext>();
        storeContext .Stores.Add(new Store { Title = "John's store", Address = "NY", Description = "Electronics best deals", SellerId = "john@mail.com" });
        storeContext .Stores.Add(new Store { Title = "Jennifer's store", Address = "Sydney", Description = "Fashion", SellerId = "jennifer@mail.com" });
        storeContext .SaveChanges();
        return storeContext ;
    }
    

    我重读错误,最后注意到了主要的词

    无法跟踪实体类型“商店”的实例,因为已经跟踪了另一个具有{'Id'}相同键值的实例

    所以必须有一些孤儿跟踪的实例阻止我使用商店 . 我没有保存对 s1s2 的任何引用,因此即使在离开其声明和初始化范围之后,它也必须是 storeContext 存储对插入对象的引用 . 从数据库对象查询的's why I was unable update variables normally and also why my '已分配了所有导航属性(延迟加载与此无关) . 以下代码解决了我的所有问题 .

    public static StoreContext ConfigureStoreContext(IServiceCollection services)
    {
        services.AddDbContext<StoreContext>(c =>
            c.UseInMemoryDatabase(Guid.NewGuid().ToString()).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking));
    
        var serviceProvider = services.BuildServiceProvider();
        var storeContext = serviceProvider.GetRequiredService<StoreContext>();
        var s1 = new Store { Title = "John's store", Address = "NY", Description = "Electronics best deals", SellerId = "john@mail.com" };
        var s2 = new Store { Title = "Jennifer's store", Address = "Sydney", Description = "Fashion", SellerId = "jennifer@mail.com" }
        storeContext .Stores.Add(s1);
        storeContext .Stores.Add(s2);
        storeContext .Entry<Store>(s1).State = EntityState.Detached;
        storeContext .Entry<Store>(s2).State = EntityState.Detached;
        storeContext .SaveChanges();
        return storeContext ;
    }
    

    这是dbContext应受范围限制的众多原因之一 . 谢谢hint .

相关问题