如何用C#实现数据库的软删除模式?如何配置?

来源:这里教程网 时间:2026-02-21 17:27:36 作者:

在C#中实现数据库的软删除模式,核心是标记数据为“已删除”而不是真正从数据库中移除。通常通过添加一个 IsDeleted 字段来实现,并结合 Entity Framework Core(EF Core)进行查询过滤和操作控制。

1. 添加 IsDeleted 字段

在实体类中增加一个布尔类型的 IsDeleted 属性,用于标识该记录是否已被软删除。

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsDeleted { get; set; } = false;
}

2. 配置全局查询过滤器(EF Core)

使用 EF Core 的 HasQueryFilter 方法,在 OnModelCreating 中配置,使所有查询自动排除已删除的数据。

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        .HasQueryFilter(p => !p.IsDeleted);
}

这样每次查询 Product 时,EF Core 会自动加上 WHERE IsDeleted = 0 条件。

3. 重写 SaveChanges 实现软删除逻辑

拦截 SaveChanges 方法,将删除操作转换为更新 IsDeleted 字段。

public override int SaveChanges()
{
    foreach (var entry in ChangeTracker.Entries<Product>())
    {
        if (entry.State == EntityState.Deleted)
        {
            entry.Property("IsDeleted").CurrentValue = true;
            entry.State = EntityState.Modified;
        }
    }
    return base.SaveChanges();
}

这段代码检查所有被标记为删除的实体,改为设置 IsDeleted = true 并改为修改状态,避免物理删除。

4. 可选:支持删除时间和删除人

如果需要审计信息,可以扩展字段:

public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public bool IsDeleted { get; set; } = false;
    public DateTime? DeletedAt { get; set; }
    public string DeletedBy { get; set; }
}

SaveChanges 中补充赋值:

if (entry.State == EntityState.Deleted)
{
    entry.Property("IsDeleted").CurrentValue = true;
    entry.Property("DeletedAt").CurrentValue = DateTime.UtcNow;
    // 可根据上下文设置 DeletedBy,如从用户服务获取
    entry.State = EntityState.Modified;
}

5. 查询包含已删除数据(特殊场景)

某些管理功能可能需要查看已删除数据,可通过 IgnoreQueryFilters() 绕过过滤:

var deletedProducts = context.Products
    .IgnoreQueryFilters()
    .Where(p => p.IsDeleted)
    .ToList();
基本上就这些。软删除的关键在于统一拦截删除操作并配合查询过滤,确保业务逻辑不会误读已删除数据,同时保留恢复能力。

相关推荐