TransactionScope 分布式事务

news/2024/8/26 17:16:05

TransactionScope 分布式事务

 TransactionScope是.Net Framework 2.0滞后,新增了一个名称空间。它的用途是为数据库访问提供了一个“轻量级”[区别于:SqlTransaction]的事物。使用之前必须添加对 System.Transactions.dll 的引用。

      下列代码就是一个正在创建的事务,这个事务自身还封装了多个数据库查询。只要任意一个 SqlCommand 对象引发异常,程序流控制就会跳出 TransactionScope 的 using 语句块,随后,TransactionScope 将自行释放并回滚该事务。由于这段代码使用了 using 语句,所以 SqlConnection 对象和 TransactionScope 对象都将被自动调用Dispose()释放。由此可见,只需添加很少的几行代码,您就可以构建出一个事务模型,这个模型可以对异常进行处理,执行结束后会自行清理,此外,它还可以对命令的提交或回滚进行管理。 

// 创建TransactionScope
using  (TransactionScope tsCope  =   new  TransactionScope())
{
  
using (SqlConnection cn2005 = new SqlConnection(someSql2005))
  
{
    SqlCommand cmd 
= new SqlCommand(sqlUpdate, cn2005);
    cn2005.Open();
    cmd.ExecuteNonQuery();
  }

  
using (SqlConnection cn2005 = new SqlConnection(anotherSql2005))
  
{
    SqlCommand cmd 
= new SqlCommand(sqlDelete, cn2005);
    cn2005.Open();
    cmd.ExecuteNonQuery();
  }


  tsCope.Complete();
}

   连接字符串关键字(Enlist)
      SqlConnection.ConnectionString 属性支持关键字 Enlist,该关键字指示 System.Data.SqlClient 是否将检测事务上下文并自动在分布式事务中登记连接。 如果 Enlist=true,连接将自动在打开的线程的当前事务上下文中登记。 如果 Enlist=false,SqlClient 连接不会与分布式事务进行交互。 Enlist 的默认值为 true。 如果连接字符串中未指定 Enlist,若在连接打开时检测到一个,连接将自动在分布式事务中登记。  

Server = (local)SQL2005;Database = Northwind;Integrated Security = SSPI;auto - enlist = false

       上面所看到的示例中我们使用了TransactionScope的默认设置。TransactionScope有三种模式:

 

TransactionScopeOptions描述
Required如果已经存在一个事务,那么这个事务范围将加入已有的事务。否则,它将创建自己的事务。
RequiresNew这个事务范围将创建自己的事务。
Suppress如果处于当前活动事务范围内,那么这个事务范围既不会加入氛围事务 (ambient transaction),也不会创建自己的事务。当部分代码需要留在事务外部时,可以使用该选项。
      您可以在代码的任何位置上随是查看是否存在事务范围,具体方法就是查看 System.Transactions.Transaction.Current 属性。如果这个属性为“null”,说明不存在当前事务。
      若要更改 TransactionScope 类的默认设置,您可以创建一个 TransactionOptions 对象,然后通过它在 TransactionScope 对象上设置隔离级别和事务的超时时间。TransactionOptions 类有一个 IsolationLevel 属性,通过这个属性可以更改隔离级别,例如从默认的可序列化 (Serializable) 改为ReadCommitted,甚至可以改为 SQL Server 2005 引入的新的快照 (Snapshot) 级别。(请记住,隔离级别仅仅是一个建议。大多数数据库引擎会试着使用建议的隔离级别,但也可能选择其他级别。)此外,TransactionOptions 类还有一个 TimeOut 属性,这个属性可以用来更改超时时间(默认设置为 1 分钟)。
      下列代码中使用了默认的 TransactionScope 对象及其默认构造函数。也就是说,它的隔离级别设置为可序列化 (Serializable),事务的超时时间为 1 分钟,而且 TransactionScopeOptions 的设置为 Required。

 

TransactionOptions tOpt  =   new  TransactionOptions();
// 设置TransactionOptions模式
tOpt.IsolationLevel  =  IsolationLevel.ReadCommitted;
//  设置超时间隔为2分钟,默认为60秒
tOpt.Timeout  =   new  TimeSpan( 0 2 0 );
string  cnString  =  ConfigurationManager.ConnectionStrings[ " sql2005DBServer " ].ConnectionString);

using  (TransactionScope tsCope  =   new  TransactionScope(TransactionScopeOption.RequiresNew, tOpt))
{
  
using  (SqlConnection cn2005  =   new  SqlConnection(cnString)
  {
    SqlCommand cmd 
=   new  SqlCommand(updateSql1, cn2005);
    cn2005.Open();
    cmd.ExecuteNonQuery();
  }

  tsCope.Complete();
}

       嵌套应用
      如下列代码,假设 Method1 创建一个 TransactionScope,针对一个数据库执行一条命令,然后调用 Method2。Method2 创建一个自身的 TransactionScope,并针对一个数据库执行另一条命令。      

private   void  Method1()
{
  
using  (TransactionScope ts  =
    
new  TransactionScope(TransactionScopeOption.Required))
  {
    
using  (SqlConnection cn2005  =   new  SqlConnection())
    {
      SqlCommand cmd 
=   new  SqlCommand(updateSql1, cn2005);
      cn2005.Open();
      cmd.ExecuteNonQuery();
    }
    Method2();
    ts.Complete();
  }
}
private   void  Method2()
{
  
using  (TransactionScope ts  =
    
new  TransactionScope(TransactionScopeOption.RequiresNew))
  {
    
using  (SqlConnection cn2005  =   new  SqlConnection())
    {
      SqlCommand cmd 
=   new  SqlCommand(updateSql2, cn2005);
      cn2005.Open();
      cmd.ExecuteNonQuery();
    }
    ts.Complete();
  }
}

      总结:
      进入和退出事务都要快,这一点非常重要,因为事务会锁定宝贵的资源。最佳实践要求我们在需要使用事务之前再去创建它,在需要对其执行命令前迅速打开连接,执行动作查询 (Action Query),并尽可能快地完成和释放事务。在事务执行期间,您还应该避免执行任何不必要的、与数据库无关的代码,这能够防止资源被毫无疑义地锁定过长的时间。


http://www.niftyadmin.cn/n/1895004.html

相关文章

spring-session剖析

2019独角兽企业重金招聘Python工程师标准>>> 一、使用场景 1)一台服务器上的软负载均衡应用 2)分布式应用 二、实现方式 1)session数据存cookie 将session存储至cookie中,每次请求从cookie中读取session,缺…

css学习笔记(一)

position定位 CSS position属性用于指定一个元素在文档中的定位方式。top,right,bottom 和 left 属性则决定了该元素的最终位置。 定位类型 定位元素(positioned element)是其计算后位置属性为 relative, absolute, fixed 或 stic…

bitmap索引 MySQL_( 转 ) 数据库BTree索引、Hash索引、Bitmap位图索引的优缺点

测试于:MySQL 5.5.25当前测试的版本是Mysql 5.5.25只有BTree和Hash两种索引类型,默认为BTree。Oracle或其他类型数据库中会有Bitmap索引(位图索引),这里作为比较也一起提供。BTree索引BTree(多路搜索树,并不是二叉的)是一种常见的…

python学习笔记--变量和运算符

一、变量命名规则 1.字母、数字、下划线组成 2.不以数字开头 3.关键字(也叫保留字),不能用作变量名 4.遵循PEP8命名规范 二、变量赋值 1.赋值符号 2.多重赋值 xy123 3.多变量赋值 x,y,z123 4.交换两个变量的值 可以 a,bb,a 三、运算符 1.算数运算符 : …

mpvue重构小程序之坑点1

对于最近刚做的项目&#xff0c;想着用框架重新架构一遍&#xff0c;方便以后拓展,毕竟现在拓展方向非常大。 目前主要碰到两个略坑的问题&#xff1a; 1&#xff1a; 关于用户授权信息的按钮&#xff0c;原生是以下方式&#xff0c;使用bindgetuserinfo事件 <button stylew…

C/C++中typedef struct和struct的用法

由于对typedef理解不够&#xff0c;因此从网上摘录了一些资料&#xff0c;整理如下&#xff1a; C/C中typedef struct和struct的用法 struct _x1 { ...}x1; 和 typedef struct _x2{ ...} x2; 有什么不同&#xff1f; 其实, 前者是定义了类_x1和_x1的对象实例…

php mysql date 格式化时间_PHP+Mysql如何格式化日期时间?

写过PHPMySQL的程序员都知道有时间差&#xff0c;UNIX时间戳和格式化日期是我们常打交道的两个时间表示形式&#xff0c;Unix时间戳存储、处理方便&#xff0c;但是不直观&#xff0c;格式化日期直观&#xff0c;但是处理起来不如Unix时间戳那么自如。所以有的时候需要互相转换…

mysql中创建外键如何理解_mysql外键理解

一个班级的学生个人信息表&#xff1a;什么是外键在设计的时候&#xff0c;就给表1加入一个外键&#xff0c;这个外键就是表2中的学号字段&#xff0c;那么这样表1就是主表&#xff0c;表2就是子表。外键用来干什么为了一张表记录的数据不要太过冗余。这和软件project的模块化思…