BEGIN TRAN应放置在业务代码中还是存储过程内?
事务配置最优方案解答
优先选择仅在C#代码中配置事务,以下是三种方案的实际效果对比:
- 两处都配置事务:属于不推荐的方案。SQL Server的嵌套事务是伪实现,依赖
@@TRANCOUNT计数实现逻辑:每次执行begin tran计数+1,每次执行commit tran计数-1,只有计数归0时才会真正提交事务。如果存储过程内部执行了commit tran,外层事务回滚时虽然还能生效,但如果存储过程内部出错执行了回滚操作,会直接将@@TRANCOUNT清零,导致外层C#的事务后续操作抛出「事务计数不匹配」的异常,极容易出现逻辑bug,维护成本极高。 - 仅在存储过程中配置事务:仅适用于「该存储过程100%永远只会独立执行,不会和其他数据库操作共享事务」的极窄场景。弊端是灵活性极差,如果后续业务需要把存储过程的执行和其他SQL操作、其他存储过程调用纳入同一个原子事务,完全无法实现,业务逻辑调整时需要频繁修改存储过程,扩展性差。
- 仅在C#代码中配置事务:是绝大多数场景下的最优方案。事务边界由业务层统一管控,你可以根据业务需要把任意多个数据库操作(包括原生SQL语句、多个存储过程调用)纳入同一个事务,完全适配业务原子性要求。同时避免了嵌套事务的各类坑,存储过程只需要专注实现数据操作逻辑即可,不管是ADO.NET原生的
SqlTransaction还是TransactionScope都可以和SQL Server完美适配,逻辑清晰,可维护性和扩展性都更高。
内容的提问来源于stack exchange,提问作者carlosm
相关产品推荐
相关产品推荐

