TransactionScope 分布式事务的使用案例 以及简单说明
TransactionScope 是的.net Framework2.0版本中增加的一个新命名空间。他的用途是为数据库访问提供一个“轻量级”的事物。使用之前必须添加对 System.Transactions.dll 的引用。先介绍介绍几个简单的参数。
| 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 分钟)。
TransactionOptions opt= new TransactionOptions();
//设置TransactionOptions
opt.IsolationLevel = IsolationLevel.ReadCommitted;
// 设置超时间隔为2分钟,默认为60秒
opt.Timeout = new TimeSpan(0, 2, 0);
使用时候将
using (TransactionScope sCope = new TransactionScope(TransactionScopeOption.RequiresNew, opt))
其他和默认一样
下面做一个简单的demo 只需要添加很少的几行代码,这个模型可以对异常进行处理,执行结束后会自行清理,此外,它还可以对命令的提交或回滚进行管理
1.TransactionScope 在一个事务范围内
在app.config中
<connectionStrings>
    <add name="myCon" connectionString="Data Source=.;uid=sa;pwd=sa;database=B2C3;Asynchronous Processing=true"/>
    <add name="myCon2" connectionString="Data Source=.;uid=sa;pwd=sa;database=b2c;Asynchronous Processing=true"/>
    <add name="myCon3" connectionString="Data Source=.;uid=sa;pwd=sa;database=demo;Asynchronous Processing=true"/>
    <add name="myCon4" connectionString="Data Source=.;uid=sa;pwd=sa;database=News;Asynchronous Processing=true"/>
  </connectionStrings>
 static void Main(string[] args)
        {
           string constr = ConfigurationManager.ConnectionStrings["myCon"].ConnectionString;
            string constr2 = ConfigurationManager.ConnectionStrings["myCon2"].ConnectionString;
            string sql = "insert into [Tuser](username,pwd,age) values('新闻socpe测试','bbb',10)";
            #region 不同库的事务
            using (TransactionScope sope = new TransactionScope())
            {
                 using(SqlConnection con =new SqlConnection(constr))
                {
                    using (SqlCommand cmd = new SqlCommand(sql, con))
                    {
                        con.Open();
                      int a=  cmd.ExecuteNonQuery();
                      Console.WriteLine(a);
                    
                    }
                   
                
                }
                using (SqlConnection con = new SqlConnection(constr2))
                {
                    using (SqlCommand cmd = new SqlCommand(sql, con))
                    {
                        con.Open();
                        int b = cmd.ExecuteNonQuery();
                        Console.WriteLine(b);
}
                }
                addOtherUser();
                sope.Complete();
            }
            #endregion
sope.Complete(); 是个标示。只有全部运行才提交事务
2.嵌套 调用事务
        static void Main(string[] args)
        {
            string constr = ConfigurationManager.ConnectionStrings["myCon"].ConnectionString;
            string constr2 = ConfigurationManager.ConnectionStrings["myCon2"].ConnectionString;
            string sql = "insert into [Tuser](username,pwd,age) values('新闻socpe测试','bbb',10)";
            #region 不同库的事务
            using (TransactionScope sope = new TransactionScope(TransactionScopeOption.Required))
            {
             
                using(SqlConnection con =new SqlConnection(constr))
                {
                    using (SqlCommand cmd = new SqlCommand(sql, con))
                    {
                        con.Open();
                      int a=  cmd.ExecuteNonQuery();
                      Console.WriteLine(a);
                    
                    }
                   
                
                }
                using (SqlConnection con = new SqlConnection(constr2))
                {
                    using (SqlCommand cmd = new SqlCommand(sql, con))
                    {
                        con.Open();
                        int b = cmd.ExecuteNonQuery();
                        Console.WriteLine(b);
}
                }
                addOtherUser();
                sope.Complete();
            }
            #endregion
        }
        private static void addOtherUser()
        {
            string constr3 = ConfigurationManager.ConnectionStrings["myCon3"].ConnectionString;
            string constr4 = ConfigurationManager.ConnectionStrings["myCon4"].ConnectionString;
            string sql1 = "insert into [hr_user](username,password) values('新闻socpe测试','bbb')";
            string sql2 = "insert into [Users](username,userpwd) values('新闻socpe测试','bbb')";
            //RequiresNew 这个事务范围将创建自己的事务。 
            using(TransactionScope sope=new TransactionScope(TransactionScopeOption.RequiresNew))
            {
                using (SqlConnection con = new SqlConnection(constr3))
                {
                    using (SqlCommand cmd = new SqlCommand(sql1, con))
                    {
                        con.Open();
                        int a = cmd.ExecuteNonQuery();
                        Console.WriteLine(a);
}
                }
                using (SqlConnection con = new SqlConnection(constr4))
                {
                    using (SqlCommand cmd = new SqlCommand(sql2, con))
                    {
                        con.Open();
                        int b = cmd.ExecuteNonQuery();
                        Console.WriteLine(b);
}
                }
                sope.Complete();
            }
        
        }
总结:
现在知道了TransactionScope中的数据库操作实际是参与了其中的环境事务,将它理解为是自动建立的SqlTransaction,而嵌套在其中的TransactionScope中的数据库操作会添加到这个环境事务中(以TransactionScopeOption.Required为参数生成的TransactionScope)。
也知道了Complete方法并不是执行后,就会提交事务,而只是表明之前的动作都符合要求,只是一种确认,不执行该方法,事务便不能完成。而只有最外层TransactionScope执行了Complete方法后,在离开using块时,事务才真正的提交。所以说TransactionScope是能嵌套的。
Transaction类有一静态属性Current,在一个TransactionScope中的Complete方法执行之前可以访问,它返回的便是环境事务。
但是: 进入和退出事务都要快,这一点非常重要,因为事务会锁定宝贵的资源。最佳实践要求我们在需要使用事务之前再去创建它,在需要对其执行命令前迅速打开连接,执行动作查询 (Action Query),并尽可能快地完成和释放事务。在事务执行期间,您还应该避免执行任何不必要的、与数据库无关的代码,这能够防止资源被毫无疑义地锁定过长的时间
        }
 
                    
                     
                    
                 
                    
                
 
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号