4.1 KiB
4.1 KiB
事务与命令管道约定
仅在涉及多步写入一致性、并发控制、幂等或命令管道时读取。适用于本项目所有业务模块,锁定资源、去重范围和权限条件由各模块实际需求决定。路径相对于仓库根目录。
Service 中的事务
- DTO 非空验证和不依赖数据库的业务参数校验先于事务;依赖数据库状态的校验在获取必要状态后完成,写入前必须满足业务条件。
- 用
orm.CreateUnitOfWork()、GetOrBeginTransaction()开启工作单元。事务内相关读写统一使用work.Orm,不能混用根 ORM 使部分操作脱离事务。 - 全部写入成功后
Commit(),未提交由工作单元释放回滚。不 catch 所有异常后继续提交,不封装同义事务工具。 - 异步数据库调用传递 CancellationToken,提交前检查取消。数据库事务不覆盖外部通知、文件或第三方服务等副作用,按现有业务机制安排执行与失败处理,不默认增加额外基础设施。
- 只更新允许修改的字段。需要避免丢更新的操作使用既有锁或条件更新,并检查受影响行数;不要把“必须影响一行”套到允许无变化的幂等更新上。
并发与幂等
- 涉及金额时沿用 decimal;允许值、精度和上限由业务入口判断,可能溢出的累计运算按需要使用 checked。
- 同一操作锁定多条资源时采用稳定顺序;在锁定或并发条件保护的有效状态上判断是否允许修改。进程内锁不能替代跨进程数据库一致性。
- 业务变更与必须同步保存的流水、审计记录在同一事务提交或回滚,记录实际操作者与业务目标。
- 幂等操作明确请求号的作用范围和重复请求结果,保留现有请求号、唯一约束及处理机制;不能把某模块的去重键当作全项目统一规则。
- 去重检查和写入使用能阻止竞态的数据库约束或锁机制,不能仅无保护地先查后写。重试按接口约定复用请求号。
- MySQL 表引擎、约束、隔离及并发行为需要对应环境验证,SQLite 只承担部分持久化和回滚验证。
MediatR 管道
复用以下框架实现,按当前文件确认行为:
Core/MAX.Framework/Mediation/ValidationBehavior.csCore/MAX.Framework/Mediation/TransactionBehavior.csCore/MAX.Framework/Mediation/UnitOfWorkExecutionContext.csCore/MAX.Framework/DependencyInjection/MediatRBehaviorServiceCollectionExtensions.cs
命令携带业务输入 DTO,可信操作者由服务端上下文提供。普通 Service 方法不必建立同义命令。
- 通过
[MediatRBehavior(typeof(...))]选择必要步骤,顺序由实际依赖决定。基础输入校验先于事务;需要事务内状态的业务步骤位于事务内部。 IValidatableRequest.Validate()调用RequestValidator.Validate(Input)完成 DTO 非空校验;长度、格式、范围及组合规则仍放在 Service 或已有业务处理入口,不迁入 DTO。后续 Handler 不重复基础校验。- 不依赖数据库的业务参数校验在事务前执行,优先使用已有业务处理入口或适用的业务管道,不为单次判断机械新增一层。
- 事务内管道和 Handler 统一使用
UnitOfWorkExecutionContext.Orm。 - TransactionBehavior 统一提交、取消检查和回滚;当前实现拒绝嵌套事务命令。组合操作在同一事务用例中完成,不递归发送另一个事务命令。
- 已授权上下文是内部执行结果,不是客户端输入。保留必要上下文清理、执行顺序和重入约束,不把这些当作重复 DTO 校验删除。
- 在
IStartup.Register(IServiceRegistrar)注册 Handler,宿主通过 AddMediatRAttributedBehaviors 扫描特性。确认模块程序集被现有机制发现,不另写扫描器或重复注册。
验证
按本次变化验证成功提交、任一步骤失败时整体回滚、权限或状态拒绝时无写入、重复请求处理,以及实际操作者的审计记录。涉及管道时使用真实管道入口验证顺序和注册;并发锁验证使用对应数据库,不以单线程 SQLite 测试替代。