如何向正在运行的TransactionScope登记并获取事务提交、回滚通知?
向TransactionScope登记自定义事务资源的实现方案
核心实现思路
你需要实现.NET提供的IEnlistmentNotification接口,将自定义的事务资源登记到当前环境事务中,就能自动接收事务的提交、回滚通知。
具体实现步骤
1. 实现自定义事务登记类
这个类需要继承IEnlistmentNotification,封装你自己的事务提交、回滚逻辑:
public class ContosoTransactionEnlistment : IEnlistmentNotification { // 保存你自己的事务实例,用来执行提交/回滚 private readonly IContosoTransaction _tx; public ContosoTransactionEnlistment(IContosoTransaction tx) { _tx = tx; } // 事务管理器询问资源是否可以提交 public void Prepare(PreparingEnlistment preparingEnlistment) { try { // 这里可以做你自己的预检查逻辑,确认可以提交 preparingEnlistment.Prepared(); } catch { // 预检查失败,通知事务回滚 preparingEnlistment.ForceRollback(); } } // 收到提交通知 public void Commit(Enlistment enlistment) { _tx.Commit(); // 通知事务管理器提交完成 enlistment.Done(); } // 收到回滚通知 public void Rollback(Enlistment enlistment) { _tx.Rollback(); // 通知事务管理器回滚完成 enlistment.Done(); } // 事务状态不确定时触发(比如事务管理器故障) public void InDoubt(Enlistment enlistment) { // 按自己的业务需求处理,一般默认回滚也可以 _tx.Rollback(); enlistment.Done(); } }
2. 在业务方法中自动检测环境事务并登记
修改你对外暴露的业务方法,自动判断当前是否有运行中的TransactionScope环境事务,按需登记:
public class TurboEncabulator { public void UpendCardinalGrammeters() { IContosoTransaction tx = null; // 检测是否存在环境事务 var ambientTx = Transaction.Current; if (ambientTx != null) { // 开启你自己的事务 tx = BeginTransaction(); // 将自定义事务登记到环境事务中 // 如果是易失资源(比如内存操作)用EnlistVolatile,持久化资源用EnlistDurable ambientTx.EnlistVolatile(new ContosoTransactionEnlistment(tx), EnlistmentOptions.None); } try { // 这里写你的正常业务逻辑 // ...... } catch { // 如果没有环境事务,自行回滚 tx?.Rollback(); throw; } // 如果没有环境事务,自行提交 if (ambientTx == null) { tx?.Commit(); } } // 你原有开启事务的方法 private IContosoTransaction BeginTransaction() { // 原有逻辑实现 } }
补充说明
- 如果你的自定义资源是内存类的易失资源,直接用
EnlistVolatile即可;如果是磁盘存储类的持久化资源,需要支持故障恢复,就使用EnlistDurable方法登记。 - 可选实现
ISinglePhaseNotification接口代替IEnlistmentNotification,可以在单阶段提交场景下优化性能,减少不必要的交互。
内容的提问来源于stack exchange,提问作者Ian Boyd
相关产品推荐
相关产品推荐

