EF Core Interceptors

Mind Map Summary

  • Topic: EF Core Interceptors
  • Definition: A feature that allows you to intercept, modify, or suppress EF Core operations. Interceptors are registered with the DbContext.
  • Types of Interceptors:
    • DbCommandInterceptor: Intercepts the execution of a DbCommand.
    • DbConnectionInterceptor: Intercepts operations on a DbConnection.
    • DbTransactionInterceptor: Intercepts operations on a DbTransaction.
    • SaveChangesInterceptor: Intercepts calls to SaveChanges and SaveChangesAsync.
  • Use Cases:
    • Logging: Log SQL commands, connection events, or transaction events.
    • Auditing: Automatically set audit properties (e.g., CreatedAt, ModifiedAt) when saving changes.
    • Multi-Tenancy: Automatically add a tenant ID to all queries.
    • Performance Monitoring: Measure the time it takes to execute a command.

Practice Exercise

Implement a DbCommandInterceptor that logs the full text of every SQL command executed by EF Core to the console. Register the interceptor and show the logs generated by a simple query.

Answer

1. Create the DbCommandInterceptor:

using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;
using System.Threading;
using System.Threading.Tasks;

public class LoggingInterceptor : DbCommandInterceptor
{
    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        System.Console.WriteLine($"[COMMAND]: {command.CommandText}");
        return result;
    }

    public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = default)
    {
        System.Console.WriteLine($"[COMMAND]: {command.CommandText}");
        return new ValueTask<InterceptionResult<DbDataReader>>(result);
    }
}

2. Register the Interceptor in the DbContext:

using Microsoft.EntityFrameworkCore;

public class MyDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.AddInterceptors(new LoggingInterceptor());
    }
}

3. Run a Query and View the Logs:

When you run a query, such as context.Products.ToList(), you will see the following output in the console:

[COMMAND]: SELECT [p].[Id], [p].[Name] FROM [Products] AS [p]