You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 MVC迁移:EF6软删除拦截器适配改造方案咨询

EF6 到 EF Core 6 软删除拦截器迁移方案

一、需要补充安装的 NuGet 包

除已安装的 Microsoft.EntityFrameworkCore 和 Microsoft.EntityFrameworkCore.SqlServer,还需添加:

  • Microsoft.EntityFrameworkCore.Abstractions:提供 EF Core 拦截器相关的抽象接口与基础类型
  • Microsoft.EntityFrameworkCore.Relational:包含关系数据库通用扩展(如 SQL 命令拦截的核心 API)

二、三个类的具体修改

1. IsDeletedInterceptor.cs(拦截器核心逻辑)

EF6 的 IDbCommandInterceptor 已被 EF Core 的 DbCommandInterceptor(位于 Microsoft.EntityFrameworkCore.Diagnostics 命名空间)替代,需重写对应拦截方法并适配 EF Core 的 API:

using Microsoft.EntityFrameworkCore.Diagnostics;
using System.Data.Common;
using System.Linq;

public class IsDeletedInterceptor : DbCommandInterceptor
{
    // 拦截同步查询,自动添加软删除过滤
    public override InterceptionResult<DbDataReader> ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result)
    {
        ModifyQueryCommand(command);
        return base.ReaderExecuting(command, eventData, result);
    }

    // 拦截异步查询,同步逻辑的异步实现
    public override ValueTask<InterceptionResult<DbDataReader>> ReaderExecutingAsync(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<DbDataReader> result,
        CancellationToken cancellationToken = default)
    {
        ModifyQueryCommand(command);
        return base.ReaderExecutingAsync(command, eventData, result, cancellationToken);
    }

    // 拦截删除命令,转为软删除(UPDATE 替代 DELETE)
    public override InterceptionResult<int> NonQueryExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult<int> result)
    {
        ModifyDeleteCommand(command);
        return base.NonQueryExecuting(command, eventData, result);
    }

    // 辅助方法:修改 SELECT 语句添加软删除过滤
    private void ModifyQueryCommand(DbCommand command)
    {
        if (!string.IsNullOrEmpty(command.CommandText) 
            && command.CommandText.StartsWith("SELECT", StringComparison.OrdinalIgnoreCase)
            && !command.CommandText.Contains("IsDeleted"))
        {
            var fromIndex = command.CommandText.IndexOf("FROM", StringComparison.OrdinalIgnoreCase);
            command.CommandText = command.CommandText.Insert(fromIndex, " WHERE IsDeleted = 0");
        }
    }

    // 辅助方法:将 DELETE 转为软删除的 UPDATE
    private void ModifyDeleteCommand(DbCommand command)
    {
        if (command.CommandText.StartsWith("DELETE", StringComparison.OrdinalIgnoreCase))
        {
            var tableName = command.CommandText.Split(new[] { "FROM " }, StringSplitOptions.None)[1].Split(' ')[0];
            var whereClause = command.CommandText.Substring(command.CommandText.IndexOf("WHERE", StringComparison.OrdinalIgnoreCase));
            command.CommandText = $"UPDATE {tableName} SET IsDeleted = 1 {whereClause}";
        }
    }
}

2. InterceptorExtensions.cs(拦截器注册扩展)

EF6 的 DbConfiguration.AddInterceptor 需替换为 EF Core 的 DbContextOptionsBuilder.AddInterceptor,修改扩展方法:

using Microsoft.EntityFrameworkCore;

public static class InterceptorExtensions
{
    public static DbContextOptionsBuilder AddIsDeletedInterceptor(this DbContextOptionsBuilder options)
    {
        return options.AddInterceptor(new IsDeletedInterceptor());
    }
}

3. EntityFrameworkConfiguration.cs(配置类处理)

EF Core 已废弃 EF6 的 DbConfiguration 全局配置模式,直接删除该类即可。原配置逻辑(如注册拦截器)可移至两个位置:

  • DbContext 的 OnConfiguring 方法:
    public class YourDbContext : DbContext
    {
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.AddIsDeletedInterceptor();
            optionsBuilder.UseSqlServer("你的连接字符串");
        }
    }
    
  • Program.cs 中的 DbContext 注册:
    builder.Services.AddDbContext<YourDbContext>(options =>
    {
        options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"));
        options.AddIsDeletedInterceptor();
    });
    

三、更优替代方案(推荐)

EF Core 原生支持全局查询过滤器,比拦截器更稳定简洁,可替代拦截器实现软删除过滤:

  1. 定义软删除接口:
    public interface ISoftDelete
    {
        bool IsDeleted { get; set; }
    }
    
  2. 让所有需要软删除的实体实现该接口,然后在 DbContext 的 OnModelCreating 中配置全局过滤器:
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType))
            {
                var parameter = Expression.Parameter(entityType.ClrType, "e");
                var filter = Expression.Lambda(
                    Expression.Equal(
                        Expression.Property(parameter, nameof(ISoftDelete.IsDeleted)),
                        Expression.Constant(false)),
                    parameter);
                modelBuilder.Entity(entityType.ClrType).HasQueryFilter(filter);
            }
        }
    }
    
  3. 处理删除操作时,直接设置实体的 IsDeleted = true 并调用 SaveChanges 即可。

内容的提问来源于stack exchange,提问作者csharpdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 11:42:28