在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();
基本上就这些。软删除的关键在于统一拦截删除操作并配合查询过滤,确保业务逻辑不会误读已删除数据,同时保留恢复能力。 