FreeSql 事务与 Unit of Work:[Transactional] 事务传播如何保障业务数据一致性

FreeSql 事务与 Unit of Work:[Transactional] 事务传播如何保障业务数据一致性 FreeSql 事务与 Unit of Work[Transactional] 事务传播如何保障业务数据一致性【免费下载链接】FreeSql功能强大的对象关系映射O/RM组件支持 .NET Core 2.1、.NET Framework 4.0、Xamarin 以及 AOT。项目地址: https://gitcode.com/dotnetcore/FreeSqlFreeSql 是功能强大的 .NET 对象关系映射O/RM组件支持 .NET Core 2.1、.NET Framework 4.0、Xamarin 以及 AOT。在 FreeSql 生态中FreeSql.DbContext 提供了工作单元Unit of Work与 [Transactional] 事务传播机制让你用一个特性就把多次数据库写入绑定成要么全部成功、要么全部回滚的整体从机制上保障业务数据的一致性。先搞懂两个角色工作单元与传播行为一个类比工作单元IUnitOfWork就像一次记账会话期间所有写操作都记在同一本账上最后统一结账Commit或作废重记Rollback。传播行为Propagation决定方法被调用时是加入已有事务、新建事务还是干脆不走事务——也就是这个方法与外面正在进行的会话是什么关系。理解传播行为推荐先看这张对照表| 传播方式 | 外层已有事务 | 外层没有事务 | 典型场景 | | -- | -- | -- | -- | |Required默认 | 加入外层事务 | 新建事务 | 业务入口方法的标配 | |Supports| 加入外层事务 | 非事务执行 | 可能跑在事务里、也可能独立跑的通用方法 | |Mandatory| 加入外层事务 | 抛异常 | 必须被外层事务包裹的私有步骤 | |NotSupported| 挂起外层非事务执行 | 非事务执行 | 日志、审计等不想被回滚的写入 | |Never| 抛异常 | 非事务执行 | 明确禁止在事务中执行的操作 | |Nested| 以嵌套方式执行 | 新建事务 | 需要独立提交的中间步骤 |[Transactional] 特性背后的三步魔法TransactionalAttribute 基于 Rougamo 源码织入在目标方法进出时自动接管事务核心就三步方法进入OnEntry从服务容器取出 UnitOfWorkManager调用Begin(传播方式, 隔离级别)创建或加入工作单元方法退出OnExit无异常 →Commit()提交有异常 →Rollback()回滚最后Dispose()释放异步方法特殊处理若方法返回Task事务会等待 Task 真正完成后才提交或回滚所以async业务方法同样安全。唯一的前置动作是在中间件里把请求作用域的服务容器交给特性特性织入时代码无法自动感知当前请求app.Use(async (context, next) { TransactionalAttribute.SetServiceProvider(context.RequestServices); await next(); });完整装配流程可参考示例工程Startup.cs。UnitOfWorkManager 内部的三种工作单元形态UnitOfWorkManager.Begin 会根据传播方式返回三种形态之一这也是传播二字真正的实现Original真实事务从连接池借出一条专用连接并开启数据库事务事务开始后才正式生效Virtual虚拟事务当外层已有事务时内层方法拿到的不是新事务而是外层事务的代理——Commit()为空操作、Rollback()才会真正触发回滚从而内层失败拖垮外层、内层成功不影响外层Nothing无事务NotSupported/Never等场景下的轻量对象不开事务但仍支持实体变化跟踪。此外UnitOfWorkManager.Binding可以把仓储IBaseRepository或 DbContext 绑定到当前事务之后它们的所有读写的连接都自动跟随同一事务——你不再需要手动传递DbTransaction或WithTransaction。UnitOfWork 的提交与回滚还会触发实体变化报告EntityChangeReport可用于审计、日志、统一维护审计字段等扩展详见 DbContext 说明文档。最小可运行示例aspnetcore_transaction 示例工程仓库自带的 aspnetcore_transaction 示例展示了一整套标准装配// 1. 依赖注入IFreeSql 单例 UnitOfWorkManager 请求级Scoped services.AddSingletonIFreeSql(Fsql); services.AddScopedUnitOfWorkManager(); services.AddFreeRepository(null, typeof(Startup).Assembly); // 2. 自定义仓储构造时注入 UnitOfWorkManager使用其 Orm public SongRepository(UnitOfWorkManager uowm) : base(uowm?.Orm, uowm) { } // 3. 业务方法打上 [Transactional]默认 Required 传播 [Transactional] public async Taskobject GetAsync(...) { await repoSong.InsertAsync(new Song()); await repoDetail.InsertAsync(new Detail()); return 111; }要点解读UnitOfWorkManager注册为Scoped即每个 HTTP 请求一个工作单元管理器事务边界天然与请求对齐仓储使用uowm.OrmUnitOfWorkManager 暴露的带事务的 IFreeSql读写自动挂到当前事务上更细的业务方法可参考 SongService.cs它演示了同步、Task、async三种方法形态下的[Transactional]用法。实战要点传播方式怎么选SQLite 注意示例代码里特意注明sqlite 不能嵌套事务会锁库的见 SongService.cs。如果你使用 Sqlite 等不支持保存点/嵌套事务的数据库避免盲目使用Nested。几条实用建议| 场景 | 推荐传播方式 | 理由 | | -- | -- | -- | | Controller / 业务入口方法 |Required默认 | 有无外层事务都能正常工作 | | 必须随外层一起成败的步骤 |Mandatory| 脱离事务直接抛异常快速暴露调用问题 | | 日志、审计等不想被回滚的写入 |NotSupported| 挂起外层事务独立执行 | | 需要独立提交的中间步骤 |Nested| 中间步骤失败不影响整体 | | 只读查询混在业务里 |Supports| 有事务搭便车没有也不强开 |总结一致性的保障链条FreeSql 用一条清晰的链条保障业务数据一致性[Transactional]在方法进出时自动Begin / Commit / Rollback异步方法也可靠Propagation六种传播行为决定方法与外层事务的关系配合 UnitOfWorkManager 的 Virtual 包装实现内层共享外层事务绑定后的仓储与 DbContext 自动共用同一事务连接免去手工传递DbTransactionUnitOfWork 的States字典与实体变化报告为审计和扩展留足空间。想进一步动手建议从 FreeSql.DbContext 的说明文档和 UnitOfWorkManager 源码读起——传播行为的全部规则就浓缩在Begin方法的那段switch里非常值得逐行精读。【免费下载链接】FreeSql功能强大的对象关系映射O/RM组件支持 .NET Core 2.1、.NET Framework 4.0、Xamarin 以及 AOT。项目地址: https://gitcode.com/dotnetcore/FreeSql创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考