CommittableTransaction和TransactionScope

创建可提交事务

下面的示例创建一个新的 CommittableTransaction 并提交它。

//Create a committable transaction
tx = new CommittableTransaction();

SqlConnection myConnection = new SqlConnection("server=(local)\\SQLExpress;Integrated Security=SSPI;database=northwind");
SqlCommand myCommand = new SqlCommand();

//Open the SQL connection
myConnection.Open();

//Give the transaction to SQL to enlist with
myConnection.EnlistTransaction(tx);

myCommand.Connection = myConnection;

// Restore database to near it's original condition so sample will work correctly.
myCommand.CommandText = "DELETE FROM Region WHERE (RegionID = 100) OR (RegionID = 101)";
myCommand.ExecuteNonQuery();

// Insert the first record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (100, 'MidWestern')";
myCommand.ExecuteNonQuery();

// Insert the second record.
myCommand.CommandText = "Insert into Region (RegionID, RegionDescription) VALUES (101, 'MidEastern')";
myCommand.ExecuteNonQuery();

// Commit or rollback the transaction
while (true)
{
    Console.Write("Commit or Rollback? [C|R] ");
    ConsoleKeyInfo c = Console.ReadKey();
    Console.WriteLine();

    if ((c.KeyChar == 'C') || (c.KeyChar == 'c'))
    {
        tx.Commit();
        break;
    }
    else if ((c.KeyChar == 'R') || (c.KeyChar == 'r'))
    {
        tx.Rollback();
        break;
    }
}
myConnection.Close();
tx = null;

异步提交

CommittableTransaction 类还提供用于异步提交事务的机制。事务提交可能会占用相当长的时间,因为它可能涉及多个数据库访问并可能有网络滞后时间。如果您想要在具有高吞吐量的应用程序中避免死锁,则可以使用异步提交尽可能快地完成事务工作,并且将提交操作作为后台任务执行。CommittableTransaction 类的 BeginCommitEndCommit 方法支持您这样做。

您可以调用 BeginCommit 以将延迟的提交分配给来自线程池的线程。您还可以调用 EndCommit,确定是否已实际提交事务。如果事务出于任何原因未能提交,则 EndCommit 引发事务异常。如果在调用 EndCommit 时尚未提交该事务,则在提交或中止该事务前阻塞调用方。

进行异步提交的最简单方法是提供在完成提交时要调用的回调方法。但是,您必须对用于进行该调用的原始 CommittableTransaction 对象调用 EndCommit 方法。要获取该对象,您可以终止回调方法的 IAsyncResult 参数,因为 CommittableTransaction 类实现 IAsyncResult 类。

下面的示例说明如何进行异步提交。

public void DoTransactionalWork()
{
     Transaction oldAmbient = Transaction.Current;
     CommittableTransaction committableTransaction = new CommittableTransaction();
     Transaction.Current = committableTransaction;

     try
     {
          /* Perform transactional work here */
          // No errors - commit transaction asynchronously
          committableTransaction.BeginCommit(OnCommitted,null);
     }
     finally
     {
          //Restore the ambient transaction 
          Transaction.Current = oldAmbient;
     }
}
void OnCommitted(IAsyncResult asyncResult)
{
     CommittableTransaction committableTransaction;
     committableTransaction = asyncResult as CommittableTransaction;   
     Debug.Assert(committableTransaction != null);
     try
     {
          using(committableTransaction)
          {
               committableTransaction.EndCommit(asyncResult);
          }
     }
     catch(TransactionException e)
     {
          //Handle the failure to commit
     }
}

 

posted on 2016-07-27 17:28  空明流光  阅读(1027)  评论(0编辑  收藏  举报

导航