Introduction

When building applications with Entity Framework Core (EF Core), developers often need to execute custom logic during database operations.

Common requirements include:

Traditionally, this logic was added directly inside services or repositories, leading to duplicated code and maintenance challenges.

EF Core Interceptors provide a cleaner solution by allowing developers to intercept and customize database operations before or after they execute.

In this article, you'll learn what EF Core Interceptors are, how they work, and explore practical real-world use cases with examples.

What Are EF Core Interceptors?

EF Core Interceptors are components that allow developers to intercept database operations and execute custom logic during the Entity Framework pipeline.

They act as middleware for EF Core operations.

Example flow:

Application
    ↓
EF Core
    ↓
Interceptor
    ↓
Database

Interceptors can inspect, modify, or react to operations before they reach the database.

Why Use Interceptors?

Consider an application where every database change must be audited.

Without interceptors:

Service A
   ↓
Audit Logic

Service B
   ↓
Audit Logic

Service C
   ↓
Audit Logic

The same code gets repeated.

With interceptors:

EF Core Interceptor
        ↓
Audit Logic
        ↓
All DbContext Operations

This centralizes behavior and reduces duplication.

Common Types of EF Core Interceptors

EF Core provides several interceptor types.

SaveChanges Interceptor

Triggers during:

Insert
Update
Delete

Useful for:

Command Interceptor

Triggers when SQL commands execute.

Useful for:

Connection Interceptor

Triggers during database connections.

Useful for:

Creating a SaveChanges Interceptor

A common scenario is auditing.

Example:

using Microsoft.EntityFrameworkCore.Diagnostics;

public class AuditInterceptor
    : SaveChangesInterceptor
{
    public override ValueTask<
        InterceptionResult<int>>
    SavingChangesAsync(
        DbContextEventData eventData,
        InterceptionResult<int> result,
        CancellationToken cancellationToken = default)
    {
        Console.WriteLine(
            "Saving Changes");

        return base.SavingChangesAsync(
            eventData,
            result,
            cancellationToken);
    }
}

This executes whenever SaveChanges() runs.

Registering an Interceptor

Register the interceptor in DbContext.

builder.Services
    .AddDbContext<AppDbContext>(
    options =>
    {
        options.UseSqlServer(
            connectionString);

        options.AddInterceptors(
            new AuditInterceptor());
    });

The interceptor now applies automatically.

Real-World Use Case: Auditing

Many applications need to track:

Example entity:

public class Product
{
    public string Name { get; set; }

    public DateTime CreatedAt
    { get; set; }

    public DateTime UpdatedAt
    { get; set; }
}

Interceptor:

entity.UpdatedAt =
    DateTime.UtcNow;

Every update automatically records the modification date.

No additional code is needed in services.

Real-World Use Case: Soft Delete

Instead of physically deleting records:

DELETE FROM Products

Many systems use soft deletes.

Entity:

public bool IsDeleted
{
    get;
    set;
}

Interceptor:

entity.IsDeleted = true;

Result:

Record Remains
      ↓
Marked As Deleted

Useful for:

Real-World Use Case: SQL Query Logging

Command interceptors can log SQL statements.

Example:

public class QueryInterceptor
    : DbCommandInterceptor
{
    public override InterceptionResult
        ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult result)
    {
        Console.WriteLine(
            command.CommandText);

        return result;
    }
}

This helps developers understand what SQL EF Core generates.

Real-World Use Case: Performance Monitoring

Organizations often monitor slow queries.

Example:

Query Start
      ↓
Execute SQL
      ↓
Measure Duration

Interceptor:

var stopwatch =
    Stopwatch.StartNew();

Benefits:

Real-World Use Case: Multi-Tenant Applications

Suppose a SaaS application serves multiple customers.

Each query must automatically filter data.

Example:

Tenant A
     ↓
Only Tenant A Data

Interceptors can inject tenant information before queries execute.

This helps enforce tenant isolation.

Interceptors vs Middleware

Developers often compare these features.

Middleware

Works at HTTP request level.

Request
    ↓
Middleware
    ↓
Controller

Best for:

EF Core Interceptors

Work at database level.

Application
     ↓
EF Core
     ↓
Interceptor
     ↓
Database

Best for:

Each serves a different purpose.

Advantages of EF Core Interceptors

Interceptors provide several benefits.

These advantages become more valuable as applications grow.

Best Practices

When using EF Core Interceptors:

Following these practices improves maintainability and performance.

Conclusion

Entity Framework Core Interceptors provide a powerful way to customize database operations without cluttering application code. They allow developers to centralize auditing, logging, soft deletes, performance monitoring, and other cross-cutting concerns directly within the EF Core pipeline.

Whether you're building enterprise applications, SaaS platforms, or APIs, EF Core Interceptors can help create cleaner, more maintainable, and more scalable architectures. By using interceptors strategically, developers can reduce duplication, improve visibility into database operations, and enforce consistent behavior across the entire application.