EF Core SaveChanges拦截器怎么用 EF Core ISaveChangesInterceptor教程

22次阅读

SaveChanges拦截器是在调用SaveChanges或SaveChangesAsync前后自动触发的钩子,用于统一处理数据变更逻辑,如自动填充时间戳、审计日志、业务校验或阻止非法保存;通过Addinterceptors注册,实现ISaveChangesInterceptor接口的SavingChanges(保存前)和SavedChanges(保存后)方法。

EF Core SaveChanges拦截器怎么用 EF Core ISaveChangesInterceptor教程

SaveChanges拦截器是干什么的

它是在调用SaveChangesSaveChangesAsync前后自动触发的钩子,不用改DbContext代码就能统一处理数据变更逻辑。比如自动填充创建/更新时间、记录谁改了数据、做业务校验、写审计日志,甚至临时阻止非法保存。

怎么注册一个SaveChangesInterceptor

在DI容器配置DbContext时,用AddInterceptors方法注入实现类:

  • ASP.net Core常规项目中,在Program.cs里这样写:

services.AddDbContext(options =>
  options.Usesqlserver(connectionString)
  .AddInterceptors(new AuditSaveChangesInterceptor()));

  • Aspire项目需用ConfiguredbContext避免服务解析问题:

builder.ConfigureDbContext((provider, options) =>
  options.AddInterceptors(provider.GetRequiredService()));

怎么写一个基础的拦截器

实现ISaveChangesInterceptor接口,重点关注两个方法:

EF Core SaveChanges拦截器怎么用 EF Core ISaveChangesInterceptor教程

办公小浣熊

办公小浣熊是基于商汤大语言模型的原生数据分析产品,

EF Core SaveChanges拦截器怎么用 EF Core ISaveChangesInterceptor教程 460

查看详情 EF Core SaveChanges拦截器怎么用 EF Core ISaveChangesInterceptor教程

  • SavingChanges:保存前触发,可修改实体状态、校验、或直接SuppressWithResult中断保存
  • SavedChanges:保存成功后触发,适合发通知、记日志、清理缓存

示例:自动设置UpdatedAt字段

public class AuditSaveChangesInterceptor : ISaveChangesInterceptor
{
  public InterceptionResult SavingChanges(DbContextEventData eventData, InterceptionResult result)
  {
    var context = eventData.Context;
    if (context != NULL)
    {
      var entries = context.ChangeTracker.Entries()
        .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);
      foreach (var entry in entries)
      {
        if (entry.State == EntityState.Added)
          entry.Entity.CreatedAt = DateTime.UtcNow;
        entry.Entity.UpdatedAt = DateTime.UtcNow;
      }
    }
    return result;
  }
  public void SavedChanges(DbContextEventData eventData, int result)
  {
    // 可在此处记录日志,比如“共保存5条记录”
  }
}

常见注意点

拦截器是无状态的,别在类里存实例字段;如需依赖服务(如ILogger),通过构造函数注入;多个拦截器按注册顺序执行;若在SavingChanges中返回带结果的InterceptionResult,EF会跳过后续操作——这适合做权限拦截或软删除替代。

基本上就这些。

text=ZqhQzanResources