逻辑删除组件
逻辑删除组件(DbLogicDelete)用于对实体记录执行软删除,即把记录标记为已删除而不真正移除数据。
概述
逻辑删除不会从数据库删除记录,而是把目标的删除标记置为已删除状态,使常规查询不再返回这些数据。相比物理删除,逻辑删除可恢复、可追溯,是默认推荐的删除方式。
组件针对「操作对象」执行删除,删除范围由上游传入的记录决定,并支持「跳过操作权限校验」。
配置项
| 配置项 | 说明 |
|---|---|
| 操作对象 | 要删除的实体对象,必填 |
| 跳过操作权限校验 | 开启 后不校验当前用户对目标对象的操作权限 |
| 输出到最终结果 | 开启后该组件结果作为接口返回值 |
执行流程
与物理删除的区别
| 对比项 | 逻辑删除(DbLogicDelete) | 物理删除(DbDelete) |
|---|---|---|
| 数据保留 | 保留 | 永久移除 |
| 可恢复 | 可恢复 | 不可恢复 |
| 常规查询 | 默认过滤已删除 | 无此记录 |
| 适用场景 | 业务数据删除 | 清理数据、测试数据 |
使用场景
- 业务单据的作废、撤销
- 用户主动删除但需保留痕迹的数据
- 需要支持回收站的场景
下一步
属性明细
以下内容面向技术实现与 AI 检索,说明逻辑删除组件的节点元数据。
节点元数据
逻辑删除组件由 FlowCmpType.DbLogicDelete 标识:
| 属性名 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|
type | string | 组件类型 | 固定为 "DbLogicDelete" |
MetaObjectId | string(GUID) | 目标实体对象 | 缺省取当前接口所属对象 |
SkipOperationPermission | string(bool) | 是否跳过操作权限校验 | "true" / "false" |
IsFinalResult | string(bool) | 是否输出到最终结果 | "true" / "false" |
order | string | 同级排序 | 例:"5" |
元数据存储示例
{
"ID": "logicdel1",
"type": "DbLogicDelete",
"MetaObjectId": "3f9c0b2e-2d3a-4e6f-9c11-0f7a5b8d2e10",
"SkipOperationPermission": "false",
"IsFinalResult": "false",
"order": "5"
}
删除标记
逻辑删除完成后,记录的删除标记字段(IsDeleted)被置为 true,实体默认查询会过滤该标记为 true 的记录。
服务端执行逻辑
本组件在服务端的实现类为 DbLogicDeleteComponentManager,组件类型为 FlowComponentTypeEnum.DbLogicDelete。本节说明服务端如何解析节点配置、做行级权限过滤并以软删除方式落库。
执行时机与场景
- 流程引擎分两个阶段调用组件:保存/发布时进入校验阶段(
_VerifyAsync),运行期进入执行阶段(_ExecuteAsync)。 - 组件基类为
TriggerComponentManagerBase(继承InterfaceComponentManagerBase)。节点IsDisabled为"true"时整体跳过;每次进入递增RecursionDeep,超过 100 抛ProcessCycleOrNodeMoreThanLimit。 - 对象触发器场景下
ExecuteAsync会额外记录节点耗时与成功/失败。
输入数据来源
节点配置全部取自 context.CurrentNode.Meta,所有 meta 值均以字符串形式存储。本组件读取的 key 为 MetaObjectId、IsFinalResult、SkipOperationPermission;type、IsDisabled 由基类读取。
待删除记录按以下优先级解析:
- 上游结果优先:
context.CmpResult为List<ObjectData>时直接使用; - 否则回退请求数据:
context.Request深克隆后的Request.List。
两者都为空时执行 ExecuteNextAsync(空操作)。
执行步骤
- 校验:
MetaObjectId为空抛OperationObjectNotFound;查询MetaObject不存在抛MetaObjectNotFoundById;若目标为员工信息对象(System_UserInformation_MetaObjectId)抛UserInfoObjectNotAllowedLogicalDelete。 - 特殊对象拦截(执行阶段开头):员工信息 →
UserInfoNotAllowedLogicalDelete;组织(System_Organization_MetaObjectId)→OrganizationNotAllowedLogicalDelete;系统文件(System_ChameleonFile_Id)→SystemFileNotAllowedLogicalDelete。 - 取数:按优先级解析列表,为空则跳过;条数 >
BatchOperationThreshold(100)抛SingleOperationDataCannotMorethanXCount。 - Id 校验:任一条目
_id非法 GUID 抛DataIdNotGuidFormat(附该_id)。 - 模型解析:
GetMetaObjectByIdFromCacheAsync读取对象定义。 - 权限校验:操作权限与 MOU 行级权限,见「权限校验」。
- 构造软删除数据:为每个 id 生成
ObjectData { Id, IsDeleted = true, ModifiedBy = 当前用户, ModifiedTime = DateTimeOffset.UtcNow }。 - 落库:见「数据操作与 SQL 形态」。
- 回写上下文后进入下游。
数据操作与 SQL 形态
await chameleonDbContext.BatchUpdateAsync(metaObject.Code, updateObjectDataList);
即通过 IChameleonDbContext.BatchUpdateAsync 把记录的 isdeleted 置为 true(软删除),而不是物理删除。System.UserInformation、System.Organization、System.ChameleonFile 等系统对象被禁止逻辑删除。
输出与上下文
context.CmpResult = list(原始入参列表,而非软删除后的实体)。context.DicParam写入:BizDataIds(逗号拼接的_id)、MetaObjectCode、MetaObjectId;GetMetaObjectByIdFromCacheAsync另写入ChameleonMetaObjectId、ChameleonMetaObjectCode。IsFinalResult为"true"时:设置context.TransferResult.List/Total与context.Result = ResponseResult<List<ObjectData>>.Success([.. list.Take(1)]).Total(list.Count),最终结果只返回第一条记录、total为删除条数。
事务、批量阈值与限制
- 批量阈值:单次条数不得超过
CommonConst.BatchOperationThreshold = 100,超出抛SingleOperationDataCannotMorethanXCount。 - 系统对象(员工信息、组织、系统文件)禁止逻辑删除。
- 组件自身不显式开启事务,写入由
IChameleonDbContext执行;是否处于事务中以IChameleonDbContext.InTransaction为准。
权限校验
- 操作权限:未跳过时调用
permissionService.VerifyPermissionAsync(PermissionRequest.CreateMetaObjectDataOperation(metaObject._id, MetaObjectDataOperationType.Delete))。 - MOU/行级权限:未跳过时以
CombineDataPermissionFilterAsync(context, metaObject, FilterBuilder.In(CommonConst._id, ids), MouPermissionStageEnum.Delete)生成条件,再用GetListAsync(metaObject.Code, filter, ["_id"])取回有权限的_id,与入参取交集;交集为空抛NoPermissionOperateData。 - 跳过标志:
SkipOperationPermission取节点 meta 或DicParam任一为"true";SkipMouPermission仅从DicParam["SkipMouPermission"]读取。
异常与校验
| 触发条件 | 错误常量 |
|---|---|
MetaObjectId 为空 | OperationObjectNotFound |
| 目标对象不存在 | MetaObjectNotFoundById |
| 员工信息对象(校验阶段) | UserInfoObjectNotAllowedLogicalDelete |
| 员工信息对象(执行阶段) | UserInfoNotAllowedLogicalDelete |
| 组织对象 | OrganizationNotAllowedLogicalDelete |
| 系统文件对象 | SystemFileNotAllowedLogicalDelete |
| 条数超过 100 | SingleOperationDataCannotMorethanXCount |
_id 非 GUID | DataIdNotGuidFormat |
| MOU 过滤后无可操作数据 | NoPermissionOperateData |
所有异常经 ErrorException 包装,附带组件类型、接口 id、节点 id 定位信息;文案取自 locale 资源。