The Error
You see this when saving:
InvalidOperationException: The instance of entity type 'User' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.
Quick Fix - 30 Seconds
EF Core is tracking 2 copies of the same entity. Detach one or use AsNoTracking().
Wrong - Crashes:
var user1 = await _db.Users.FindAsync(1);
var user2 = new User { Id = 1, Name = "New" };
_db.Users.Update(user2); // CRASH - user1 already tracked
await _db.SaveChangesAsync();
Right - Option 1: Update the tracked entity:
var user = await _db.Users.FindAsync(1);
user.Name = "New";
await _db.SaveChangesAsync(); // WORKS
Right - Option 2: Use AsNoTracking for reads:
var user1 = await _db.Users.AsNoTracking().FirstAsync(u => u.Id == 1);
var user2 = new User { Id = 1, Name = "New" };
_db.Users.Update(user2); // WORKS
await _db.SaveChangesAsync();
Why This Happens
EF Core's change tracker can only track ONE instance per primary key. When you load an entity, EF tracks it. If you then attach a NEW object with the same ID, EF throws.
Step-by-Step: How to Debug
- Find duplicate loads: Search for 2 queries loading the same ID
- Check for
new Entity { Id = x }: Don't create new objects for updates - Add
AsNoTracking(): For read-only queries that don't need updates - Clear tracker if needed:
_db.ChangeTracker.Clear();nuclear option
Common Scenarios
- Repository pattern:
GetById()tracks, thenUpdate()attaches new instance - AutoMapper:
_mapper.Map<User>(dto)creates new tracked entity - Parallel updates: 2 requests updating same record simultaneously
Best Practice for.NET 8
1. Read with AsNoTracking if you won't update: 3x faster
2. Update pattern: Load, modify, save. Don't create new objects
public async Task UpdateUserAsync(UserDto dto)
{
var user = await _db.Users.FindAsync(dto.Id); // Tracked
_mapper.Map(dto, user); // Map onto tracked entity
await _db.SaveChangesAsync();
}
No comments yet. Be the first to share your thoughts!