Efcore: Data seeding can leave tracked entities in the context

Created on 10 Jun 2019  路  3Comments  路  Source: dotnet/efcore

I'm getting this error in some unit tests using the last preview version (3.0.0-preview5.19227.1) of the Microsoft.EntityFrameworkCore.InMemory package. The same issue is not reproducible with the stable version 2.2.4.

The exception that I'm receiving:

Exception message: System.ArgumentException : An item with the same key has already been added. Key: 3eb00b42-a9f0-4012-841d-70ebf3ab7474
Stack trace: at System.Collections.Generic.Dictionary`2.TryInsert(TKey key, TValue value, InsertionBehavior behavior)
   at Microsoft.EntityFrameworkCore.InMemory.Storage.Internal.InMemoryTable`1.Create(IUpdateEntry entry)
   at Microsoft.EntityFrameworkCore.InMemory.Storage.Internal.InMemoryStore.ExecuteTransaction(IList`1 entries, IDiagnosticsLogger`1 updateLogger)
   at Microsoft.EntityFrameworkCore.InMemory.Storage.Internal.InMemoryDatabase.SaveChangesAsync(IList`1 entries, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at VinylStore.Catalog.Infrastructure.CatalogContext.SaveEntitiesAsync(CancellationToken cancellationToken) in /Users/samuele.resca/Projects/EFCore.IssueSample/Catalog/src/VinylStore.Catalog.Infrastructure/CatalogContext.cs:line 27
   at VinylStore.Catalog.Infrastructure.Tests.ItemRepositoryTests.should_add_new_item(String jsonEntity) in /Users/samuele.resca/Projects/EFCore.IssueSample/Catalog/tests/VinylStore.Catalog.Infrastructure.Tests/ItemRepositoryTests.cs:line 89
--- End of stack trace from previous location where exception was thrown ---
Failed   VinylStore.Catalog.Infrastructure.Tests.ItemRepositoryTests.should_update_item(jsonEntity: "{ \"Id\": \"b5b05534-9263-448c-a69e-0bbd8b3eb90e\""...)
Error 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.
Stack Trace:
   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, Boolean modifyProperties)
   at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry.set_State(EntityState value)
   at VinylStore.Catalog.Infrastructure.Repositories.ItemRepository.Update(Item item) in /Users/samuele.resca/Projects/EFCore.IssueSample/Catalog/src/VinylStore.Catalog.Infrastructure/Repositories/ItemRepository.cs:line 48
   at VinylStore.Catalog.Infrastructure.Tests.ItemRepositoryTests.should_update_item(String jsonEntity) in /Users/samuele.resca/Projects/EFCore.IssueSample/Catalog/tests/VinylStore.Catalog.Infrastructure.Tests/ItemRepositoryTests.cs:line 118
--- End of stack trace from previous location where exception was thrown ---

Steps to reproduce

The following repository contains the issue: EFCore.IssueSamples

To reproduce the error execute inside the project folder:

dotnet build
dotnet test

If you revert to the 2.2.4 version, all the packages it works fine.
I've tested both the int type and the Guid type.

Further technical details

EF Core version: (found in project.csproj or packages.config)
Database Provider: Microsoft.EntityFrameworkCore.InMemory
Operating system: MacOSX
IDE: VsCode

closed-fixed customer-reported type-bug

All 3 comments

Note for triage: the issue here is that the context instance is still tracking seed data after EnsureCreated is called. /cc @AndriySvyryd

@samueleresca As a workaround for now you can move your EnsureCreated to run on a separate context instance. For example:
```C#
using (var context = new TestCatalogContext(options))
{
context.Database.EnsureCreated();
}

using (var context = new TestCatalogContext(options))
{
var sut = new ItemRepository(context);
sut.Add(entity);

await sut.UnitOfWork.SaveEntitiesAsync();

}
```

@ajcvickers thanks for the workaround

@ajcvickers fb846974a4f25a386a224342f26daecae2cc1bea changed creating a new StateManager to creating an UpdateAdapterFactory with the shared StateManager instance when called without a model (InMemory and Cosmos). The fix would be to pass in the model instance.

Was this page helpful?
0 / 5 - 0 ratings