.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 原生支持全局查询过滤器,比拦截器更稳定简洁,可替代拦截器实现软删除过滤:
- 定义软删除接口:
public interface ISoftDelete { bool IsDeleted { get; set; } } - 让所有需要软删除的实体实现该接口,然后在 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); } } } - 处理删除操作时,直接设置实体的
IsDeleted = true并调用SaveChanges即可。
内容的提问来源于stack exchange,提问作者csharpdev
相关产品推荐
相关产品推荐

