如何加入 TransactionScope?

问题描述 投票:0回答:1

简短版

我如何加入正在进行的TransactionScope

长版

如果您使用TransactionScope,您可以创建“环境”交易:

using (TransactionScope scope = new TransactionScope())
{
   //...stuff happens, then you complete...

   // The Complete method commits the transaction. 
   scope.Complete();
}

那有什么用呢?嗯,.NET 框架中有一些类知道如何通过检查

static
:

来检查是否存在环境正在进行的事务

这让他们知道有一笔交易正在进行中。

例如,如果您有一些任意数据库操作,否则不考虑事务:

void DropStudents()
{
   using (var cmd = connection.CreateCommand())
   {
      cmd.CommandText = "DROP TABLE Students;";
      cmd.ExecuteNonQuery();
   }
}

如果你把它放在 TransactionScope 的中间:

using (TransactionScope scope = new TransactionScope())
{
   DropStudents();

   // The Complete method commits the transaction. 
   scope.Complete();
}

突然间您的 ADO.net 操作处于事务中;并且可以回滚。

自动开始事务、提交和回滚

SqlClient库知道要检查:

  • 系统.交易.当前

并自动在内部:

  • 开始数据库事务
  • 调用 Scope.Complete
  • 时提交数据库事务
  • 回滚范围时回滚数据库事务

这一切都只是魔法。

  • 不知何故,
    DbConnection
    收到了致电
    .Commit
  • 的通知
  • 不知何故,
    DbConnection
    收到了呼叫
    .Rollback
  • 的通知

我该怎么做?

我有一堂课也有交易。而不是强迫呼叫者打电话:

using (IContosoTransaction tx = turboEncabulator.BeginTransaction())
{
   try
   {
      turboEncabulator.UpendCardinalGrammeters();
   }
   catch (Exception ex)
   {
      tx.Rollback();
      throw;
   }
   tx.Commit();
}

如果他们能打电话就好了:

turboEncabulator.UpendCardinalGrammeters();

我的代码将简单地检查:

  • 系统.交易.当前

如果有交易正在进行,我会:

  • 开始交易
  • 等待通知提交
  • 或等待通知回滚

但是我该怎么做呢?

我如何向正在进行的 TransactionScope 注册自己以获取这些通知?

.net transactionscope
1个回答
10
投票

其实没那么糟糕。

  1. 通过查看是否分配了

    System.Transactions.Transaction.Current
    来检查是否有正在进行的事务。如果有,交易中
    Enlist

    //Enlist in any current transactionScope if one is active
    if (System.Transactions.Transaction.Current != null)
       System.Transactions.Transaction.Current.EnlistVolatile(this, EnlistmentOptions.None);
    

    我传递

    this
    作为将通过其必须实现的
    IEnlistmentNotification
    接口获取通知回调的对象。

  2. 然后需要实现

    IEnlistmentNotification
    的四种通知方法:

    • void Prepare(PreparingEnlistment preparingEnlistment);
    • void Commit(Enlistment enlistment);
    • void InDoubt(Enlistment enlistment);
    • void Rollback(Enlistment enlistment);

实际的实现是简单的样板通知:

  • 准备:交易管理器要求您投票决定交易是否适合提交:
    • 投票:致电
      preparingEnlistment.Prepared();
    • 投票:致电
      preparingEnlistment.ForceRollback();
  • 承诺:做你的事情来承诺并声明你已完成入伍:
    • enlistment.Done();
  • InDoubt:交易经理与参与交易的其他人失去联系的通知。回复让他们知道您已完成入伍:
    • enlistment.Done();
  • Rollback:事务正在回滚的通知。进行任何类型的回滚工作,并让他们知道您已完成征募:
    • enlistment.Done();

或更全面

public void Prepare(PreparingEnlistment preparingEnlistment)
{
   //The transaction manager is asking for our vote if the transaction
   //can be committed

   //Vote "yes" by calling .Prepared:
   preparingenlistment.Prepared();

   //Vote "no" by calling .ForceRollback:
   //preparingEnlistment.ForceRollback();
}

public void Commit(Enlistment enlistment)
{
   //The transaction is being committed - do whatever it is we do to commit.

   //Let them know we're done with the enlistment.
   enlistment.Done();
}

public void InDoubt(Enlistment enlistment)
{
   //Do any work necessary when indoubt notification is received.
   //This method is called if the transaction manager loses contact with one or more participants, 
   //so their status is unknown.
   //If this occurs, you should log this fact so that you can investigate later whether any of the 
   //transaction participants has been left in an inconsistent state.

   //Let them know we're done with the enlistment.
   enlistment.Done();
}

public void Rollback(Enlistment enlistment)
{
   //If any resource manager reported a failure to prepare in phase 1, the transaction manager invokes 
   //the Rollback method for each resource manager and indicates to the application the failure of the commit.

   //Let them know we're done with the enlistment.
   enlistment.Done();
}
© www.soinside.com 2019 - 2024. All rights reserved.