简体   繁体   中英

The instance of entity type 'Item' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked

I am aware that such question has already been asked, but solution did not help me.

[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();
}

Message: System.InvalidOperationException: The instance of entity type 'Item' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked. When attaching existing entities, ensure that only one entity instance with a given key value is attached. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting key values.

interesting that exception is the same even if no item retreived from db, like so

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

Had the same problem with EF core 2.2. I never experianced this with other applications.

Ended up rewriting all my update functions somehow like this:

public bool Update(Entity entity)
{
    try
    {   
       var entry = _context.Entries.First(e=>e.Id == entity.Id);
       _context.Entry(entry).CurrentValues.SetValues(entity);
       _context.SaveChanges();
       return true;
    }
    catch (Exception e)
    {
         // handle correct exception
         // log error
         return false;
    }
}

Numerous issues I've been running into have one nasty root. In a nutshell: I've learned the hard way why dbContext is scoped rather than singleton. Here is Store type, but the issue was the same. Here is simplified test initialization code

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 ;
}

I reread error and finally noticed the main word

The instance of entity type 'Store' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked

So there has to be some orphan tracked instance preventing me from working with store. I did not save any references to s1 or s2 , so it must be storeContext storing references on inserted objects even after leaving scope of their declaration and initialization. That's why I was unable update variables normally and also why my 'queried' from db objects had all their navigation properties assigned (lazy loading has little to do with this). The following code resolved all my issues.

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 ;
}

That is one of many reasons why dbContext should be limited by a scope. Thanks for the hint .

Alexandar's answer, which was to disable tracking completely, solved my issue, but I got worried since I didn't know what this would do to the rest of my application. So I went to the Microsoft docs and found this :

You should not disable change tracking if you want to manipulate entity instances and persist those changes to the database using SaveChanges().

This method sets the default behavior for all contexts created with these options, but you can override this behavior for a context instance using QueryTrackingBehavior or on individual queries using the AsNoTracking(IQueryable) and AsTracking(IQueryable) methods.

So the solution for me was to disable tracking only when needed . So I solved my issue by using this in the other part of my code that retrieved the same entry from the database:

var entry = await context
    .SomeDbTable
    .AsNoTracking() // this is what you're looking for
    .Find(id);

I had same problem while I was copying some records in database by Entity Framework and changing one column that was other's entity key. Tracking mode change did not fix the issue.

The issue was fixed by properly setting primary key in EntityTypeConfiguration, to contain the changed value here described as x.EntityTwoKey.

builder.HasKey(x => new { x.EntityOneKey, x.EntityTwoKey });

In my case I hit this error when running SaveChanges twice inside of two IFs statements. I moved the SaveChanges outside of those two blocks of code. Just a side note in my service layer it is querying the data with AsNoTracking();

if (user.SendPaymentStatus)
{
    user.SendPaymentStatus = false;
    saveChanges = true;
    //_userService.SaveChanges(user, false);

    msg = GetPaymentHTML(user.MasterNodeName, user.Payee, DbMasterNode.LastPaidUtc);
    Framework.Email.SendEmail(email, "MasterNode Payment - " + user.MasterNodeName, msg);        
}

if (user.SendNodeStatus)
{
    user.SendNodeStatus = false;
    saveChanges = true;
    //_userService.SaveChanges(user, false);

    msg = GetStatusHTML(user.MasterNodeName, user.Payee, DbMasterNode.CurrentStatus, DbMasterNode.LastSeenUtc);
    Framework.Email.SendEmail(email, "MasterNode Down - " + user.MasterNodeName, msg);
}

if (saveChanges)
{
    user.SendPaymentStatus = false;
    _userService.SaveChanges(user, false);
}

For me was this the solution:

public void Update(int id, T obj)
        {
            var entry = table.Find(id);
            _context.Entry(entry).CurrentValues.SetValues(obj);
        }

Based on the solution Bryan gave. I think I use newer version of EF/Automapping. This works for me.

I was getting the same problem when was trying to update the value. then i found the proble i was using this.

services.AddDbContext<StudentContext>(option => option.UseSqlServer(Configuration.GetConnectionString("databasename")),ServiceLifetime.Singleton);

then i remove lifetime and it worked well for me.

services.AddDbContext<StudentContext>(option => option.UseSqlServer(Configuration.GetConnectionString("databasename")));

在我的情况下,在我将主键列Id设置为 Identity 列后,上述问题得到了解决。

i got some similar error when i wanted to update data, and i found out i could fix it by clearing the property context. Here is what a did. It's not the same problem but it's the same error, so i think it can be fixed the same way, clearing the context seems to be a good solution because it's the reason of whats happening.

context.ChangeTracker.Clear();

context.Cliente.Update(cliente);

context.SaveChanges();

We recently run into the same issue when adding multiple new items with identity column id set to 0. We are using OracleDataAccess client for EF core 3, we set the sequence number for the new entities when we do saveChanges(), but it errors out when we try to add() if there's already another item with id=0.

The fix we did is making sure the configuration for the identity column is correct:

1.) Set the key

builder.HasKey(t => t.Id);

2.) Set the database generate option correctly

[Column("ID"), DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public virtual int Id { get; set; }

or fluent equivalent:

builder.Property(t => t.Id)
            .ValueGeneratedOnAdd();

We did not do second step correctly and was setting as DatabaseGeneratedOption.None, then EF core failed on add.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

Related Question The instance of entity type 'Entity' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type <T> cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type Model cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type ‘Bus’ cannot be tracked because another instance with the same key value for {‘Id’} is already being tracked The instance of entity type 'AppUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type 'IdentityUser' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type 'Bookmark' cannot be tracked because another instance with the same key value for {'ID'} is already being tracked The instance of the entity type cannot be tracked because another instance with the same key value pair for{'Id'} is already being tracked The instance of entity type 'Article' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked The instance of entity type 'User' cannot be tracked because another instance with the same key value for 'Id' is already being tracked
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM