数据写入组件
数据写入组件(DbInsert)用于向指定的实体对象创建一条新记录。
概述
数据写入向目标实体插入数据,通常用于「提交表单后生成业务单据」「触发流程时落库」等场景。写入的字段值来自上游组件的结果或上下文数据。
组件支持「跳过操作权限校验」,在需要以系统身份写入时开启。该组件的执行结果(新记录)可通过「输出到最终结果」返回给调用方。
配置项
| 配置项 | 说明 |
|---|---|
| 操作对象 | 要写入数据的实体对象,必填 |
| 跳过操作权限校验 | 开启后写入时不校验当前用户对目标对象的操作权限 |
| 输出到最终 结果 | 开启后该组件结果作为接口返回值 |
数据来源
写入的字段值来自上游传递给组件的数据(通常由表单提交或上游组件构造),执行时按字段映射写入目标实体。
执行流程
使用场景
- 表单提交后创建主表记录
- 流程节点自动生成业务单据
- 由触发器根据条件创建记录
注意事项
跳过操作权限校验会绕过数据安全限制,仅在系统级写入等必要场景使用。
下一步
属性明细
以下内容面向技术实现与 AI 检索,说明数据写入组件的节点元数据。
节点元数据
数据写入组件由 FlowCmpType.DbInsert 标识:
| 属性名 | 类型 | 含义 | 取值/存储值 |
|---|---|---|---|
type | string | 组件类型 | 固定为 "DbInsert" |
MetaObjectId | string(GUID) | 目标实体对象 | 缺省取当前接口所属对象 |
SkipOperationPermission | string(bool) | 是否跳过操作权限校验 | "true" / "false" |
IsFinalResult | string(bool) | 是否输出到最终结果 | "true" / "false" |
order | string | 同级排序 | 例:"2" |
元数据存储示例
{
"ID": "insert1",
"type": "DbInsert",
"MetaObjectId": "3f9c0b2e-2d3a-4e6f-9c11-0f7a5b8d2e10",
"SkipOperationPermission": "false",
"IsFinalResult": "true",
"order": "2"
}
操作对象数据源
「操作对象」下拉通过 POST /api/DataSource/GetMetaObjectDataSource 获取可选项。
服务端执行逻辑
本组件在服务端的实现类为 DbInsertComponentManager,组件类型为 FlowComponentTypeEnum.DbInsert。本节说明服务端如何解析节点配置、取数、校验与落库,是理解组件运行行为与排查问题的依据。
执行时机与场景
- 流程引擎分两个阶段调用组件:保存/发布时进入校验阶段(
_VerifyAsync),运行期进入执行阶段(_ExecuteAsync)。 - 组件基类为
TriggerComponentManagerBase(继承InterfaceComponentManagerBase)。进入任阶段前会先做通用处理:节点IsDisabled为"true"时直接跳过;每次进入递增RecursionDeep,超过 100 抛ProcessCycleOrNodeMoreThanLimit。 - 当链路运行在对象触发器场景时(上下文中存在追踪标记
_TriggerNodeCollector),ExecuteAsync会额外记录该节点的耗时与成功/失败;平台接口与审批流场景不做该记录。
输入数据来源
节点配置全部取自 context.CurrentNode.Meta,所有 meta 值均以字符串形式存储(布尔、数值、JSON 亦为字符串)。本组件读取的 key 为 MetaObjectId、IsFinalResult、SkipOperationPermission;type、IsDisabled 由基类读取。
待写入的数据按以下优先级解析:
- 上游结果优先:
context.CmpResult为List<ObjectData>时直接使用; - 否则回退请求数据:
context.Request深克隆后的Request.List。
两者都为空时组件执行 ExecuteNextAsync(空操作,不落库)。
执行步骤
按 _ExecuteAsync 实际顺序:
- 校验:
MetaObjectId为空抛OperationObjectNotFound;按 id 查询MetaObject,不存在抛MetaObjectNotFoundById。 - 取数:按优先级解析列表,为空则跳过;条数 >
BatchOperationThreshold(100)抛SingleOperationDataCannotMorethanXCount。 - 补 Id:
Id == Guid.Empty的记录生成新Guid。 - 系统默认值:
metaFieldService.ParseSystemDefaultValueAsync(metaObjectId, list)解析字段值中的@LoginUserId、@CurrentDateTime等为一等值。 - 模型解析:
GetMetaObjectByIdFromCacheAsync读取缓存中的对象定义与字段集合。 - 权限校验:见「权限校验」。
- 数据校验:
metaFieldService.DataVerificationAsync(metaObjectId, list, false)。 - 字段过滤与必要字段:移除
Fields中不在对象字段编码内的 key(_id除外);写入CreatedBy = ChameleonContext.Current.UserId、CreatedTime = DateTimeOffset.UtcNow、IsDeleted = false。 - 落库:见「数据操作与 SQL 形态」。
- 回写上下文后进入下游。
数据操作与 SQL 形态
按 MetaObject.Code 分支持久化:
| 条件 | 处理 |
|---|---|
System.UserInformation | userInformationService.BatchAddAsync(list) |
System.Organization | organizationService.BatchAddAsync(list) |
| 其他 | chameleonDbContext.BatchAddAsync(metaObject.Code, list) |
即以实体编码(metaObject.Code)为集合名、通过 IChameleonDbContext.BatchAddAsync 批量插入。IChameleonDbContext 基于 FreeSql,Id 为空时自动生成 GUID。
输出与上下文
context.CmpResult = list(写入后的对象集合,供下游组件取用)。context.DicParam写入:BizDataIds(逗号拼接的_id)、MetaObjectCode、MetaObjectId;GetMetaObjectByIdFromCacheAsync另写入ChameleonMetaObjectId、ChameleonMetaObjectCode。IsFinalResult为"true"时:context.TransferResult.List = list、context.TransferResult.Total = list.Count,并设置context.Result = ResponseResult<List<ObjectData>>.Success([.. list.Take(1)]).Total(list.Count),即最终结果只返回第一条记录、total为写入条数:
{
"action": 0,
"code": 200,
"data": [ { "_id": "…", "createdby": "…", "createdtime": "…", "isdeleted": false } ],
"total": 1
}
事务、批量阈值与限制
- 批量阈值:单次列表条数不得超过
CommonConst.BatchOperationThreshold = 100,超出抛SingleOperationDataCannotMorethanXCount。 - 组件自身不显式开启事务,批量写入由
IChameleonDbContext执行;是否处于事务中以IChameleonDbContext.InTransaction为准。 - 递归深度上限 100,用于阻止流程环路或过深节点;
IsDisabled节点整体跳过。
权限校验
- 操作权限:未跳过时调用
permissionService.VerifyPermissionAsync(PermissionRequest.CreateMetaObjectDataOperation(metaObject._id, MetaObjectDataOperationType.Insert))。 GetSkipOperationPermission(context)判定:节点 metaSkipOperationPermission或上下文DicParam["SkipOperationPermission"]任一为"true"。- 本组件不做 MOU/行级数据权限过滤。
异常与校验
| 触发条件 | 错误常量 |
|---|---|
MetaObjectId 为空 | OperationObjectNotFound |
| 目标对象不存在 | MetaObjectNotFoundById |
| 条数超过 100 | SingleOperationDataCannotMorethanXCount |
所有异常经 ErrorException 包装,附带组件类型、接口 id、节点 id 定位信息;文案取自 locale 资源。