EF Core async query continues after CancellationTokenSource cancellation
0 reputation · 10 Feb 2025, 06:08 UTC
0 reputation · 10 Feb 2025, 06:08 UTC
In supported EF Core versions, a DbContext runs an asynchronous query and passes a CancellationToken to ToListAsync. After the token source is cancelled, the application receives an exception, but it is unclear whether the database server stops executing the command or only the client stops waiting.
The goal is to determine whether EF Core reliably propagates cancellation to the underlying provider command and how CommandTimeout interacts with token-triggered cancellation. Behavior may differ between providers such as SQL Server and PostgreSQL, and the surrounding transaction scope may determine whether partial work rolls back.
Does EF Core always signal the database provider to cancel the command when a CancellationToken is triggered? Which exception type should be expected, OperationCanceledException or a provider-specific DbException? Does CommandTimeout override or combine with cancellation-token timing?
35775 reputation · 10 Feb 2025, 06:29 UTC
EF Core passes the CancellationToken to the underlying ADO.NET provider, which calls DbCommand.Cancel(). Whether the database engine actually stops executing depends on the provider implementation and the query's execution stage. You will typically see OperationCanceledException if cancellation occurs while the client is waiting; a provider-specific exception (e.g., SqlException with error 0x80004005 or PostgresException with SQLSTATE 57014) may surface if the engine processes the cancel during execution. CommandTimeout is a separate server-side limit and does not combine with or override the token.
DbCommand.ExecuteReaderAsync / ExecuteNonQueryAsync. The provider issues a vendor-specific cancel packet (TDS attention signal for SQL Server, PostgreSQL cancel request, etc.).OperationCanceledException wraps the token cancellation when the client aborts the wait. If the server receives the cancel mid-execution, the provider throws its own exception (e.g., SqlException Number -2 / 0, Npgsql.PostgresException SqlState 57014). Catch both.DbCommand.CommandTimeout (default 30 s) is enforced by the provider/server. It runs in parallel with the token; whichever fires first wins. They do not add together.DbContext must be disposed or Database.RollbackTransaction() called explicitly.| Provider | Cancel Mechanism | Typical Exception on Server-Side Cancel |
|---|---|---|
| Microsoft.Data.SqlClient | TDS Attention packet | SqlException Number -2 (timeout) or 0 (attention) |
| Npgsql | PostgreSQL cancel request (separate connection) | PostgresException SqlState 57014 (query_canceled) |
| MySqlConnector | MySQL KILL QUERY | MySqlException ErrorCode 1317 |
| Oracle.ManagedDataAccess | OCI cancel | OracleException ORA-01013 |
Note: Some providers (especially older Oracle or third-party drivers) may not implement async cancel; the query continues on the server until CommandTimeout expires.
WAITFOR DELAY '00:00:30' on SQL Server).SELECT * FROM sys.dm_exec_requests WHERE session_id = @@SPID (SQL Server) or pg_stat_activity (PostgreSQL). The row should disappear or show state = 'idle' within milliseconds.try {
await query.ToListAsync(token);
} catch (OperationCanceledException) {
// client-side cancel
} catch (DbException ex) when (ex is SqlException || ex is PostgresException) {
// server processed cancel
}
Which database provider and version are you using? The exact exception type and whether server-side cancel is supported changes the recommended catch block and whether you can rely on immediate termination.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.