首页 > 解决方案 > 如何加入 TransactionScope?

问题描述

简洁版本

我如何加入正在进行的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 操作在一个事务中;并且可以回滚。

自动 BeginTransaction、提交和回滚

SqlClient库知道要检查:

并在内部自动:

这一切都只是魔术。

我怎么做?

我有一堂课也有交易。而不是强迫调用者调用:

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

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

turboEncabulator.UpendCardinalGrammeters();

我的代码将简单地检查:

如果正在进行交易,我将:

但我该怎么做?

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

标签: .nettransactionscope

解决方案


实际上并没有那么糟糕。

  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);
    
  2. 然后您需要实现以下四种通知方法IEnlistmentNotification

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

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

  • Prepare:事务管理器要求您对事务是否可以提交进行投票:
    • 投票YespreparingEnlistment.Prepared();
    • 投票NopreparingEnlistment.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();
}

推荐阅读