Query interceptor in EF core allows developer to intercept the query before or after the execution. This provides the ability of interception, modification, or suppression of the query execution.
How to use Query Interceptor into code
EF core exposes DbCommandInterceptor base class, this base class is abstract class and has overridable methods which could be hooked into a class which is inherited DbCommandInterceptor class. Since Entity framework internally uses ADO.NET for database operations, DbCommandInterceptor class provides lifecycle methods for a query.
Code example
Create a class that inherits DbCommandInterceptor
public class QueryInterceptor :DbCommandInterceptor {
}
Override the lifecycle method which you are interested in
public class QueryInterceptor :DbCommandInterceptor {
public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command,CommandEventData eventData, InterceptionResult<DbDataReader> result){
Console.WriteLine($"Before Query execution. Query : {command.CommandText}");
return result;
}
public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result) {
Console.WriteLine($"After Query execution. Query : {command.CommandText}");
return result;
}
}
DbCommandInterceptor provides async version of these methods to support asynchronous operations
public class QueryInterceptor :DbCommandInterceptor {
public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result, CancellationToken cancellationToken = default){
return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
}
public override ValueTask<DbDataReader> ReaderExecutedAsync(DbCommand command, CommandExecutedEventData eventData, DbDataReader result, CancellationToken cancellationToken = default){
return base.ReaderExecutedAsync(command, eventData, result, cancellationToken);
}
}
Register the interceptor with DbContext:
An interceptor could be added to context using two ways :
register inside OnConfiguring method of DbContext class
public class ExampleContext : DbContext{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder){
base.OnConfiguring(optionsBuilder);
optionsBuilder.AddInterceptors(new QueryInterceptor())
}
}
List of lifecycle methods available
| Method Name | Description |
| CommandCanceled , CommandCanceledAsync | called when a command is cancelled. |
| CommandCreated | After command creation but before execution. |
| [CommandCreating](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.commandcreating?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-commandcreating(microsoft-entityframeworkcore-diagnostics-commandcorrelatedeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-data-common-dbcommand)))) | Before a command is created |
| CommandFailed, CommandFailedAsync | Called when execution of a command has failed with an exception. |
| CommandInitialized | Called after EF has initialized CommandText and other command configuration. |
| DataReaderClosing, DataReaderClosingAsync | Called just before EF intends to call Close(). |
| DataReaderDisposing | Called when execution of a DbDataReader is about to be disposed. |
| NonQueryExecuted, NonQueryExecutedAsync | Called immediately after EF calls ExecuteNonQuery(). |
| [NonQueryExecuting](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.nonqueryexecuting?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-nonqueryexecuting(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-int32)))), [NonQueryExecutingAsync](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.nonqueryexecutingasync?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-nonqueryexecutingasync(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-int32))-system-threading-cancellationtoken)) | Called just before EF intends to call ExecuteNonQuery(). |
| ReaderExecuted, ReaderExecutedAsync | Called immediately after EF calls ExecuteReader(). |
| [ReaderExecuting](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.readerexecuting?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-readerexecuting(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-data-common-dbdatareader)))), [ReaderExecutingAsync](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.readerexecutingasync?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-readerexecutingasync(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-data-common-dbdatareader))-system-threading-cancellationtoken)) | Called just before EF intends to call ExecuteReader(). |
| ScalarExecuted, ScalarExecutedAsync | Called immediately after EF calls ExecuteScalar(). |
| [ScalarExecuting](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.scalarexecuting?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-scalarexecuting(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-object)))), [ScalarExecutingAsync](https://learn.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.diagnostics.idbcommandinterceptor.scalarexecutingasync?view=efcore-7.0#microsoft-entityframeworkcore-diagnostics-idbcommandinterceptor-scalarexecutingasync(system-data-common-dbcommand-microsoft-entityframeworkcore-diagnostics-commandeventdata-microsoft-entityframeworkcore-diagnostics-interceptionresult((system-object))-system-threading-cancellationtoken)) | Called just before EF intends to call ExecuteScalar(). |
Resources