本文转自MSDN网站:Transaction 类 - 编写事务性应用程序 - 使用可提交事务实现显式事务

.NET Framework 类库
Transaction 类

注意:此类在 .NET Framework 2.0 版中是新增的。

表示事务。

命名空间:System.Transactions
程序集:System.Transactions(在 system.transactions.dll 中)

语法
C#
[SerializableAttribute] 
public class Transaction : IDisposable, ISerializable
备注
System.Transactions 命名空间同时提供基于 Transaction 类的显式编程模型,以及使用 TransactionScope 类的隐式编程模型,在后一种模型中,事务由该基础结构自动管理。强烈建议使用更为方便的隐式模型进行开发。若要开始,请参见 使用事务范围实现隐式事务 主题。有关编写事务性应用程序的更多信息,请参见 编写事务性应用程序

Transaction 类包含开发人员用来实现用于登记的资源管理器的方法。它还提供用于克隆事务和控制当前事务上下文的功能。使用静态 Current 属性可获得当前事务(如果已设置)。
继承层次结构

该类型对于多线程操作是安全的。

 

编写事务性应用程序

作为事务性应用程序的程序员,您可以利用 System.Transactions 命名空间提供的两种编程模型来创建事务。您可以通过使用 Transaction 类来利用显式编程模型,或者使用 TransactionScope 类来利用隐式编程模型,在该模型中通过基础结构自动管理事务。推荐采用隐式事务模型进行开发。您可以在 使用事务范围实现隐式事务主题中找到有关如何使用事务范围的更多信息。

这两种模型都支持在程序达到一致状态时提交事务。如果提交成功,事务将被持久提交。如果提交失败,事务将中止。如果应用程序无法成功完成事务,它将尝试中止事务并消除事务的影响。

本节内容

创建事务

System.Transactions 命名空间提供两种用于创建事务的模型。在以下主题中将说明这两种模型。

使用事务范围实现隐式事务

描述 System.Transactions 命名空间如何使用 TransactionScope 类支持创建隐式事务。

使用可提交事务实现显式事务

描述 System.Transactions 命名空间如何使用 CommittableTransaction 类支持创建显式事务。

事务管理升级

在某一事务需要访问其他应用程序域中的资源时,或者如果您想要在其他持久性资源管理器中登记,该事务将自动升级到由 MSDTC 管理。在 事务管理升级主题中将介绍事务升级。

并发

使用 DependentTransaction 管理并发主题说明了如何通过使用 DependentTransaction 类在异步任务之间实现并发。

COM+ Interop

与企业级服务和 COM+ 事务的互操作性主题说明了如何使您的分布式事务与 COM+ 事务交互。

诊断

诊断跟踪描述如何使用 System.Transactions 基础结构生成的跟踪代码排除应用程序中的错误。

在 ASP.NET 内工作

在 ASP.NET 中使用 System.Transactions 主题描述如何成功地在 ASP.NET 应用程序内使用 System.Transactions

使用可提交事务实现显式事务

CommittableTransaction 类为应用程序提供了一个使用事务的显式方法,此方法与隐式使用 TransactionScope 类的方法正好相反。此方法十分适合于想要跨多个函数调用或多个线程调用使用相同事务的应用程序。与 TransactionScope 类不同,为了提交或中止事务,应用程序编写者需要明确调用 CommitRollback 方法。

CommittableTransaction 类的概述

CommittableTransaction 类是从 Transaction 类派生的,因此提供后者所具有的全部功能。具体的用途就是 Transaction 类上的 Rollback 方法,该类还可用于回滚 CommittableTransaction 对象。

Transaction 类与 CommittableTransaction 类相似,但不提供 Commit 方法。这使您可以将事务对象(或其克隆)传递到其他方法(可能在其他线程上),同时仍控制何时提交事务。调用的代码能够对事务进行登记和投票,但只有 CommittableTransaction 对象的创建者才能够提交事务。

在使用 CommittableTransaction 类时,您应该注意以下事项:

  • 创建 CommittableTransaction 事务并不设置环境事务。您需要具体设置和重置环境事务,以确保资源管理器根据需要基于正确的事务上下文操作。设置当前环境事务的方法是在全局 Transaction 对象上设置静态 Current 属性。

  • CommittableTransaction 对象不能重复使用。一旦提交或回滚了 CommittableTransaction 对象后,就不能在事务中再次使用它。即,不能将它设置为当前环境事务上下文。

 

创建可提交事务

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


 

Code

 

创建 CommittableTransaction 的实例并不自动设置环境事务上下文。因此,对于资源管理器的任何操作并不是该事务的一部分。全局 Transaction 对象上的静态 Current 属性用于设置或检索环境事务,并且应用程序必须手动设置它,以确保资源管理器可以参与该事务。最好保存旧的环境事务,然后在您完成使用 CommittableTransaction 对象后还原它。

要提交事务,您需要显式调用 Commit 方法。要回滚某一事务,您应该调用 Rollback 方法。需要特别注意的是,在提交或回滚 CommittableTransaction 前,涉及该事务的所有资源仍被锁定。

可以跨函数调用和线程使用 CommittableTransaction 对象。但是,在发生故障时,由应用程序开发人员来处理异常并具体调用 Rollback 方法。

异步提交

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

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

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

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

 

C#
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
     }
}