I want to log the call stack when DbUpdateConcurrencyException
is thrown. It is thrown when I call DbContext.SaveChangesAsync
.
However, the stack trace does not show the calling chain of methods, it starts with SaveChangesAsync in my code and goes up into the EfCore implementation.
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ThrowAggregateUpdateConcurrencyExceptionAsync>d__11.MoveNext()
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ConsumeResultSetAsync>d__5.MoveNext()
at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.<ConsumeAsync>d__3.MoveNext()
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__50.MoveNext()
at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.<ExecuteAsync>d__50.MoveNext()
at Microsoft.EntityFrameworkCore.SqlServer.Update.Internal.SqlServerModificationCommandBatch.<ExecuteAsync>d__17.MoveNext()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.<ExecuteAsync>d__9.MoveNext()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__106.MoveNext()
at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.<SaveChangesAsync>d__110.MoveNext()
at Microsoft.EntityFrameworkCore.SqlServer.Storage.Internal.SqlServerExecutionStrategy.<ExecuteAsync>d__7`2.MoveNext()
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__64.MoveNext()
at Microsoft.EntityFrameworkCore.DbContext.<SaveChangesAsync>d__64.MoveNext()
at MyProject.MyContext.<SaveChangesAsync>d__180.MoveNext() in C:ProjectsMyProjectMyContext.cs:line 315
I call SaveChangesAsync from multiple places in my code, and one of places where it fails occasionally would be
public async Task UpdateOrder(Order order)
{
ValidateModel(order);
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException e)
{
_logger.LogDebug(e, "Failed to update...");
throw;
}
catch (Exception e)
{
_logger.LogDebug(e, "Failed to update...");
throw;
}
}
and the SaveChangesAsync on my context would also be pretty standard
public override async Task SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
SetUpdatedAt();
await base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
}
, so, in this case, I would expect to see UpdateOrder
in the stack trace and others calling it – up to the controller – and further non-interesting to me methods.
If I set a breakpoint and check the exception, it does not have an inner exception on it
My app is a .Net 7 web app and I inject context on Startup.ConfigureServices
services.AddDbContext<MyContext>((serviceProvider, options) =>
{
options.UseSqlServer(sqlConnectionString);
});
Am I doing something wrong? Is it possible to see my calling methods? Would it be introducing inefficiency if there is a solution?