efcore: The instance of entity type 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 numerous times, but solutions did not help me. I try to unit test my code in XUnit, but have numerous issues with EF Core, here is one of them.
// db init
public static StoreContext ConfigureStoreContext(IServiceCollection services, ITestOutputHelper output)
{
services.AddDbContext<StoreContext>(c =>
c.UseInMemoryDatabase(Guid.NewGuid().ToString()));
var serviceProvider = services.BuildServiceProvider();
var context = serviceProvider.GetRequiredService<StoreContext>();
StoreContextSeed.SeedStoreAsync(context);
return context;
}
[Fact]
public async Task UpdateAsync()
{
string newTitle = "newTitle1";
int newBrandId = 3;
//var item = await storeContext.Items.AsNoTracking().FirstOrDefaultAsync(); // result is the same
var item = new Item()
{
Id = 1,
BrandId = newBrandId,
CategoryId = 1,
MeasurementUnitId = 1,
StoreId = 1,
Title = newTitle
};
storeContext.Entry(item).State = EntityState.Detached; // has no effect, could be removed.
//if assign Deleted, then get error "can not update deleted item"
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();
}
Further technical details
EF Core version: 2.1 Database Provider: InMemory Operating system: IDE: (Visual Studio 2017 15.7)
Test Name: UnitTests.Services.StoreServiceTests.UpdateAsync
Test FullName: UnitTests.Services.StoreServiceTests.UpdateAsync
Test Source: C:\Users\kozachenkoav\source\repos\OctopusStore\UnitTests\Services\StoreServiceTests.cs : line 56
Test Outcome: Failed
Test Duration: 0:00:02,242
Result StackTrace:
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.ThrowIdentityConflict(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.IdentityMap`1.Add(TKey key, InternalEntityEntry entry, Boolean updateDuplicate)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.StartTracking(InternalEntityEntry entry)
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry.SetEntityState(EntityState oldState, EntityState newState, Boolean acceptChanges)
at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.set_State(EntityState value)
at Infrastructure.Data.EfRepository`1.UpdateAsync(T entity) in C:\Users\kozachenkoav\source\repos\OctopusStore\Infrastructure\Data\EfRepository.cs:line 54
at Infrastructure.Services.StoreService.UpdateAsync(Store store) in C:\Users\kozachenkoav\source\repos\OctopusStore\Infrastructure\Services\StoreService.cs:line 29
at UnitTests.Services.StoreServiceTests.UpdateAsync() in C:\Users\kozachenkoav\source\repos\OctopusStore\UnitTests\Services\StoreServiceTests.cs:line 71
--- End of stack trace from previous location where exception was thrown ---
Result Message: System.InvalidOperationException : The instance of entity type 'Store' 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
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 52
- Comments: 41 (3 by maintainers)
what’s the point of using EF if, instead of writing queries, you have to write additional code to avoid such bollocks ??
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
I reread error and finally noticed the main word
So there has to be some orphan tracked instance preventing me from working with store. I did not save any references to
s1ors2, so it must bestoreContextstoring 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.That is one of many reasons why dbContext should be limited by a scope. Thanks for the hint.
Hi
I have fixed this using the following code: var entity = await DbContextInMemory.FindAsync<EntityName>(EntityId); //To Avoid tracking error DbContextInMemory.Entry<EntityName>(entity).State = EntityState.Detached;
Thank you for the recommendation, @svipandi it works perfectly:
It works for me by this order,
1- context.Customers.Update/Add(customer); 2- context.SaveChanges();
3- context.Entry(customer).State = EntityState.Detached;
I noticed that you’re setting Item.Id when you create the object. Is that by any chance a database generated Id? If so, it may work to not set that value.
The same error comes up with in-memory DB unit tests anytime you try to do something like this:
Hope that helps. Paul
@svipandi check carefully places where you created context instance. once you added object via context instance, tracking won’t stop (except when you explicitly detach the very same object you added) , so you have to limit the scope of your context instance.
dec 2020 - I had to disabled change query tracking form the from the dbContext , this is what worked for me :
services.AddDbContext<ApiDbContext>(options => { options.UseNpgsql(Configuration.GetConnectionString(“DefaultConnection”)).UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking); });
I am using EF Core 3.1 InMemory Database Provider. To resolve this issue I had to Detach Each Entry of the dbContext And Set DbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;.
The below code worked for me
Hi,
// I used this part above.Category category = categoryService.GetById(categoryCreateDto.Id);// I also received an error because I am rebuilding it.Category mappedCategory = mapper.Map<Category>(categoryCreateDto);//Category mappedCategory = mapper.Map(categoryCreateDto, category);categoryService.Update(mappedCategory);I have fixed this using the following code: I’ve edited here like this.
Category mappedCategory = mapper.Map(categoryCreateDto, category);I didn’t create another new category. I used the existing one.
@titscrypto Please open a new issue and include a small, runnable project/solution or complete code listing that demonstrates the behavior you are seeing.
I also had this issue using xUnit. I’m creating a DbContext with the UseInMemoryDatabase() option, adding some mock data, then injecting that context into the classes I’m testing.
What resolved the tracking errors was disposing the DbContext that I used to insert the mock data then injecting a new DbContext instance with the same options into the test code.
Update 2 months later: I got this again. This time the fix was change the IDs of mocked entities from 0-10 to 1-11.
Why was this issue closed? I am seeing the same behavior.
Using NoTracking before using context. {YourContext}.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
Hi all,
I have same issue.I develop generic repository with .net core 2.1.1 Web api. I used AddSingleton DbContext on DependencyInjection . Get,GetAll,Post,Delete is working. But Put(Update) is not working.Please give me advice.
Controller
Generic Repository UpdateAsync
Edit:
I solved the issue.Closed the lazyLoading and after use asnotracking but I want to get relational models.How can I solve this?
Best Regards, Onur
Have you set your dbContext to Notracking Behaviour. Something like this DbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
I faced this issue when using
UseInMemoryDatabasein xunit testing. my case was:the problem is after (1), product is “cached” in dbset
Localproperty (see Local)so in my generic repository, I added 1 more condition before update:
and my
IsDetachedmethod is:notes:
hope this help.
@OnurSevket
here is you problem, mate. DbContext instance won’t let any object go. if you’ve added (or retrieved without AsNoTracking()) object, it will keep reference to it (even if you don’t save it explicitly), therefore this object will always be tracked. Singleton DbContext doesn’t really make sense, I would recommend you to add DbOptions as a singleton like so
DbContextOptions<DbContext> contextOptions = new DbContextOptionsBuilder<DbContext>().UseInMemoryDatabase("Context").Options; services.AddSingleton(contextOptions );and DbContext as scoped. Hope this helps.have you tried https://stackoverflow.com/questions/36856073/the-instance-of-entity-type-cannot-be-tracked-because-another-instance-of-this-t
It’s better to Clear ChangeTracking After ContextSaveChanges.
_context.ChangeTracker.Clear();This is case when you use InMemory database and this is why it is not a RDBMS so you should use SqlLite instead of InMemory . SqlLite is a RDBMS and I used it for unit Testing and working fine now.
@ajcvickers the issue cropped up for me when testing a local Azure function app. The function app instantiates an instance of a
DbContextfor each request. The error went away after restarting the function app. I’m concerned that even though theDbContextis created for each request, some internal bits are hanging around for the life of the app, not just the request.