如何添加自定义EntityState枚举?软删除特例处理咨询
实现区分软删除与硬删除的自定义实体状态
问题背景
我项目里用了软删除机制,逻辑是检测EntityState.Deleted的实体,给DeletedAt字段赋值当前时间,再把实体状态改成Modified。但现在有一张表需要直接硬删除数据行,不想走软删除流程,所以想加个新的实体状态来区分两种删除操作,该怎么实现?
解决方案
系统自带的EntityState枚举是密封的没法直接扩展,不过我们可以通过自定义状态枚举+实体标记接口的方式来实现需求,一步步来:
1. 定义自定义实体状态枚举
先做一个扩展枚举,补充硬删除的状态选项:
public enum CustomEntityState { Unchanged = EntityState.Unchanged, Added = EntityState.Added, Modified = EntityState.Modified, Deleted = EntityState.Deleted, Detached = EntityState.Detached, // 新增用于标记硬删除的状态 HardDeleted }
2. 创建标记接口标识硬删除实体
给需要硬删除的表对应的实体类实现这个空接口,方便后续快速识别:
// 空接口,仅用作标记 public interface IHardDeletable {} // 举个例子:你的硬删除表实体 public class TemporaryData : IHardDeletable { // 实体属性... public int Id { get; set; } public string Content { get; set; } }
3. 修改软删除逻辑,区分处理两种删除
这里提供两种实用的实现方式,你可以根据场景选:
方式一:基于接口标记自动区分
适合固定需要硬删除的实体,修改你原来的软删除代码:
var allEntries = ChangeTracker.Entries().ToList(); // 只给非硬删除标记的实体执行软删除逻辑 var softDeleteEntries = allEntries .Where(e => e.State == EntityState.Deleted && !e.Entity.GetType().IsAssignableTo(typeof(IHardDeletable))) .ToList(); softDeleteEntries.ForEach(e => { try { e.Property("DeletedAt").CurrentValue = DateTime.Now; e.State = EntityState.Modified; } catch (Exception) { // 可根据需求调整:比如捕获没有DeletedAt字段的实体异常,直接跳过或抛出提示 } }); // 实现了IHardDeletable的实体,EF会自动执行真正的DELETE语句,不需要额外处理
方式二:使用自定义状态手动指定
适合同一个实体可能需要两种删除方式的场景,先在删除实体时标记自定义状态:
// 删除时手动标记为硬删除 var targetEntity = dbContext.TemporaryData.Find(123); // 用EF的Tag属性存储标记,也可以自己维护一个字典 dbContext.Entry(targetEntity).Tag = "HardDelete"; dbContext.Remove(targetEntity);
然后修改处理逻辑:
var deletedEntities = ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).ToList(); deletedEntities.ForEach(e => { // 判断是否标记为硬删除,是的话跳过软删除逻辑 if (e.Tag == "HardDelete") { return; } try { e.Property("DeletedAt").CurrentValue = DateTime.Now; e.State = EntityState.Modified; } catch (Exception) { // 异常处理逻辑 } });
4. 注意事项
- 如果用接口标记的方式,建议给所有软删除实体统一实现一个
ISoftDeletable接口,里面包含DeletedAt属性,这样可以避免catch块的通用异常捕获,更精准 - 自定义状态的方式更灵活,但需要开发者在删除时明确标记,避免遗漏
- 记得把这段逻辑放到重写的
SaveChanges/SaveChangesAsync方法里,确保每次保存时都会触发
内容的提问来源于stack exchange,提问作者Safa
相关产品推荐
相关产品推荐

