事务

本章概要:

1:事务概述

2:隐式事务

3:显示事务

1:事务概述

     当您从网上书店购买书籍时,会用钱(以信贷方式)来交换书籍。如果您的信用良好,则一系列相关操作可确保您和书店可以相应地获得书籍和钱。但如果在交换期间该系列操作中的单个操作发生故障,则整个交换就会失败。结果,您就得不到书籍,而书店也得不到钱。负责使该交换取得平衡且可预测的技术称为事务处理。

     事务操作可限定于单个数据资源,如数据库或消息队列。在这种情况下,本地事务由 System.Transactions 所提供的可提升性能的事务管理器管理。当这些事务由数据资源控制时,它们具有高效性并易于管理。 

     事务也可跨多个数据资源。使用分布式事务可以将在不同系统上执行的多种不同的操作合并到一个通过或失败的操作中。在这种情况下,事务由位于每个系统中的 Microsoft 分布式事务协调器 (MSDTC) 进行协调。

     事务也可以有多个参与者。

     可使用 ADO.NET、System.EnterpriseServicesSystem.Transactions 命名空间所提供的新事务性编程模型来创建事务。

      System.Transactions 命名空间中的类所提供的基础结构通过支持在 SQL Server、ADO.NET、消息队列 (MSMQ) 和 Microsoft 分布式事务协调器 (MSDTC) 中启动的事务,使事务编程变得简单和高效。

      System.Transactions 命名空间提供基于 Transaction 类的显式编程模型和使用 TransactionScope 类的隐式编程模型,在后一种模型中,事务由该基础结构自动管理。此外,System.Transactions 命名空间还提供了用于实现资源管理器的类型。资源管理器管理事务中使用的持久或可变数据,并与事务管理器协调工作,共同为应用程序提供了原子性和隔离性的保证。由 System.Transactions 基础结构提供的事务管理器支持的事务可涉及到多个可变资源或单个持久资源。

2:隐式事务

     可采用 Transaction 类来利用显式编程模型,也可采用 TransactionScope 类来利用隐式编程模型(其中的事务将由基础结构自动管理)。建议您使用隐式事务模型进行开发。

     创建新的 TransactionScope 对象后即会启动事务范围。建议您使用 using 语句创建范围,如该代码示例中所示。

复制代码
void RootMethod()
{
     using(TransactionScope scope = new TransactionScope())
     {
          /* Perform transactional work here */
          SomeMethod();
          scope.Complete();
     }
}

void SomeMethod()
{
     using(TransactionScope scope = new TransactionScope())
     {
          /* Perform transactional work here */
          scope.Complete();
     }
}

复制代码


 

      最顶层事务范围称为根范围。

       TransactionScope 的有些重载构造函数接受 TimeSpan 类型的值,该值用于控制事务的超时。超时设置为零时表示超时无限长。无限长的超时主要对调试有用,调试过程中可能要经由逐句通过代码来隔离业务逻辑中的问题,并且在尝试确定问题期间不希望所调试的事务超时。在所有其他情况下使用无限长的超时时一定要格外小心,因为它会覆盖防止事务死锁的保护。

3:显示事务

     CommittableTransaction 类为应用程序使用事务提供了一种显式方法,而不是隐式地使用 TransactionScope 类。对于要跨多个函数调用或多个线程调用使用同一事务的应用程序,十分有用。TransactionScope 类不同,应用程序编写器需要明确调用 CommitRollback 方法以提交或中止事务。

复制代码
//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;

复制代码
原文地址:https://www.cnblogs.com/anbylau2130/p/3287567.html