Introduction
When building applications with Entity Framework Core (EF Core), developers often need to execute custom logic during database operations.
Common requirements include:
Auditing changes
Logging SQL queries
Performance monitoring
Soft deletes
Data validation
Multi-tenant filtering
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:
Auditing
Validation
Soft Deletes
Command Interceptor
Triggers when SQL commands execute.
Useful for:
SQL logging
Query analysis
Performance monitoring
Connection Interceptor
Triggers during database connections.
Useful for:
Connection tracking
Diagnostics
Monitoring
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:
Who created a record
When it was created
Who modified it
When it was modified
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:
Audit requirements
Data recovery
Compliance
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:
Identify slow queries
Optimize performance
Improve user experience
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:
Authentication
Logging
Request processing
EF Core Interceptors
Work at database level.
Application
↓
EF Core
↓
Interceptor
↓
Database
Best for:
Auditing
Query logging
Database monitoring
Each serves a different purpose.
Advantages of EF Core Interceptors
Interceptors provide several benefits.
Centralized logic
Reduced code duplication
Easier maintenance
Better auditing
Improved monitoring
Cleaner architecture
These advantages become more valuable as applications grow.
Best Practices
When using EF Core Interceptors:
Keep interceptors focused on one responsibility.
Avoid complex business logic.
Use async methods where possible.
Log only necessary information.
Monitor performance impact.
Reuse interceptors across projects when appropriate.
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.