
Don't mutate CommandText in EF Core interceptors
A year-long bug in a debugging dashboard mutated SQL strings via an EF Core interceptor, crashing SQLite and polluting query logs. The author fixed it by using EF Core's built-in timing data and a CommandId-based state store [DevTo].
Elad Ser released version 2.0 of AspNetDebugDashboard on June 13, 2026 after discovering that mutating DbCommand.CommandText inside an EF Core interceptor throws InvalidOperationException on SQLite and leaves comment junk in SQL Server logs [DevTo]. The original implementation appended a comment containing a GUID and a timestamp to every query in ReaderExecuting, then stripped it in ReaderExecuted to compute elapsed time. However, SQL Server ignored the extra /* … */ block, while SQLite rejected the mutation once the reader remained open, producing the error “An open reader is associated with this command.” The bug went unnoticed for a year because the tool was only exercised against SQL Server in production. EF Core already supplies the execution duration via CommandExecutedEventData.Duration, a TimeSpan measured by the framework itself [EF Core Docs]. The author rewrote the interceptor to read that value directly, eliminating the need for any SQL tampering. For cases where state must survive between the two callbacks, the recommended pattern is to store data in a side-car dictionary keyed by eventData.CommandId, which is the same GUID across ReaderExecuting and ReaderExecuted. This approach keeps query strings pristine and preserves compatibility with all providers, avoiding side-effects in database logs. Using EF Core's built-in Duration and CommandId keeps the interceptor safe, portable, and future-proof.
Subscribe to the broadcast.
Daily digest of the day's most important tech news. No fluff. Engineering signal only.
// delivered via substack · double-opt-in confirmation


