C
C#13mo ago
Temptica

✅ Urgent | Cannot update property in EF because another instance with the same key is being tracked

Hi, so I have following code: Basically I get a batch to update the field
var batch = await context.Batch.FirstOrDefaultAsync(b => b.BatchId == id);
if (batch == null) throw new BatchNotFoundException($"No batch found with id {id}");
context.Entry(batch).Property(b => b.Status).IsModified = true;
batch.Status = status;
var batch = await context.Batch.FirstOrDefaultAsync(b => b.BatchId == id);
if (batch == null) throw new BatchNotFoundException($"No batch found with id {id}");
context.Entry(batch).Property(b => b.Status).IsModified = true;
batch.Status = status;
I get the error on the 'entry' line. If I leave it, it doesn't update the field (yes I do commit later on in my CQRS). I have a code freeze tomorrow night so henc ethe Urgency as It's an imprtant feature the client wants which they only let us know very late... Full error
The instance of entity type 'Batch' cannot be tracked because another instance with the same key value for {'BatchId'} 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.
The instance of entity type 'Batch' cannot be tracked because another instance with the same key value for {'BatchId'} 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.
26 Replies
Angius
Angius13mo ago
Any reason you're updating this way? Usually it's
var thing = await ctx.Things.FirstOrDefaultAsync(...);
thing.Prop = newValue;
await ctx.SaveChangesAsync();
var thing = await ctx.Things.FirstOrDefaultAsync(...);
thing.Prop = newValue;
await ctx.SaveChangesAsync();
or better yet,
var rows = await ctx.Things
.Where(...)
.ExecuteUpdateAsync(e => e.SetProperty(t => t.Prop, newValue);
var rows = await ctx.Things
.Where(...)
.ExecuteUpdateAsync(e => e.SetProperty(t => t.Prop, newValue);
Also, the only time when I was ever met with this error, is when something fucky-wucky happened with asynchronous code So some async void method, an unawaited task, or other stuff like that
Temptica
TempticaOP13mo ago
never heared of the second one, will give that a shot, but the first one did not work as the value didn't get updated
Angius
Angius13mo ago
What type is batch.Status?
Temptica
TempticaOP13mo ago
Enum
Angius
Angius13mo ago
And the db you're using?
Temptica
TempticaOP13mo ago
SQL Server never had problems with the Enum before though in case you're wondering
Angius
Angius13mo ago
Yeah, it should work I'm asking because NpgSQL had issues tracking array columns for example, so thought it might be similar But an enum is straightforward
Temptica
TempticaOP13mo ago
Okay that was stupidly easy and I somehow never came across this solution on the internet, Even AI didn't suggest it. I don't understand how people trust AI soo much with their code but oh well, you're a legend for helping me out
Angius
Angius13mo ago
What was the issue?
Temptica
TempticaOP13mo ago
ExecuteUpdateAsync worked fine
Angius
Angius13mo ago
Nice
Temptica
TempticaOP13mo ago
but anything else I tried had tracking issues or just didn't update at all
Angius
Angius13mo ago
I'd still check the project for wonky async code This worked because it does the update in a single query As opposed to fetching the entity and then saving it
Temptica
TempticaOP13mo ago
it's all async so yeah
Angius
Angius13mo ago
When it's two separate queries, something can creep into the middle Especially with some stray async void controller somewhere Etc
Temptica
TempticaOP13mo ago
foreach (var b in request.Notification.ChangedBatches) { await _uow.BatchRepository.UpdateBatchStatus(b.BatchId, Status.AwaitConfirmation); } I do await it, I did use async task etc so yeah, no clue
Angius
Angius13mo ago
Yeah, this is fine But it could be async code anywhere else I'd at least run a cursory solution-wide search for async void
Temptica
TempticaOP13mo ago
which groupmate broke my code sus 😄 The frontend does have it but that shouldn't really be it right?
Angius
Angius13mo ago
Should have no impact on the backend, yeah
Temptica
TempticaOP13mo ago
yeah backend does not have any async voids
Angius
Angius13mo ago
Oh well, that's not it, then If it works it works though, that's what matters lol
Temptica
TempticaOP13mo ago
Exactly! and it saves me some lines of code, also a +
Angius
Angius13mo ago
Yep, the .Execute...() methods are probably my favourite addition to EF Core
Temptica
TempticaOP13mo ago
I really never saw them before. But imagine school actually explaining some USEFULL stuff 😄 altho I didn't see it while doing research so that's also on me
Angius
Angius13mo ago
They're fairly new, fwiw EF Core 7 or thereabouts
Temptica
TempticaOP13mo ago
okay fair enough, this is teh first year we're allowed to use .NET 7 even before they kept using .net 5 anyways, thank you very much again!

Did you find this page helpful?