经常遇到在三层架构中使用事务,而逻辑层无法使用SqlConnection的事务方法,终于找到一个可以在逻辑层使用的事务方法:使用TransactionScope:

 

using System;
using System.Data;
using System.Data.SqlClient;
using System.Transactions;
/// <summary>
/// 在项目里添加引用System.Transactions
/// </summary>


public class Test
{
    
/// 这个函数为 使用包含在两个SQL Servers中的两个连接和命令来创建事务 提供了论据。
    
/// 如果事务被成功提交则返回一个大于零的值, 如果事务被回滚则返回零
    
/// 你可以通过改变连接字符串,连接同一个服务器上的两个不同的数据库,或者修改connection2的代码
    
/// 连接另一种关系型数据库管理系统(RDBMS),比如Oracle数据库,来测试这段代码

    static public int CreateTransactionScope(string connectString1, string connectString2, string commandText1, string commandText2)
    
{
        
// 初始化返回值为零并创建一个StringWriter用来显示结果。
        int returnValue = 0;
        System.IO.StringWriter writer 
= new System.IO.StringWriter();

        
// 创建TransactionScope来执行命令, 保证所有命令像一个单个(整体)的工作全被提交或全被回滚
        using (TransactionScope scope = new TransactionScope())
        
{
            
using (SqlConnection connection1 = new SqlConnection(connectString1))
            
{
                
try
                
{
                    
// 打开连接,像轻量级事务一样自动加入到TransactionScope。
                    connection1.Open();

                    
//创建查询命令,并执行第一个命令
                    SqlCommand command1 = new SqlCommand(commandText1, connection1);
                    returnValue 
= command1.ExecuteNonQuery();
                    writer.WriteLine(
"Rows to be affected by command1: {0}", returnValue);

                    
// 如果执行到这里,说明命令1被成功执行。通过把connection2的using代码块嵌套入connection1里面,
                    
// 可以保持 服务器和网络资源 使得如果connection2被打开,有一个提交事务的机会。
                    using (SqlConnection connection2 = new SqlConnection(connectString2))
                        
try
                        
{
                            
// 打开connection2,事务被扩大为一个完整的分布式事务
                            connection2.Open();

                            
// 在第二个数据库中执行command2。
                            returnValue = 0;
                            SqlCommand command2 
= new SqlCommand(commandText2, connection2);
                            returnValue 
= command2.ExecuteNonQuery();
                            writer.WriteLine(
"Rows to be affected by command2: {0}", returnValue);
                        }

                        
catch (Exception ex)
                        
{
                            
//显示command2执行失败的信息
                            writer.WriteLine("returnValue for command2: {0}", returnValue);
                            writer.WriteLine(
"Exception Message2: {0}", ex.Message);
                        }

                }

                
catch (Exception ex)
                
{
                    
//显示command1执行失败的信息
                    writer.WriteLine("returnValue for command1: {0}", returnValue);
                    writer.WriteLine(
"Exception Message1: {0}", ex.Message);
                }

            }


            
// 用来提交事务的Complete方法. 如果事务执行异常,某个例外被抛弃,
            
// Complete方法就不会被响应,并且所有事务被回滚
            scope.Complete();
        }


        
// 如果事务被提交,返回值一定大于零
        if (returnValue > 0)
        
{
            writer.WriteLine(
"Transaction was committed.");
        }

        
else
        
{
            
// 在这里你可以附加业务逻辑。比如,你可以通过抛出事务异常通知访问者,或写入失败日志。
            writer.WriteLine("Transaction rolled back.");
        }

        
// 显示消息.
        Console.WriteLine(writer.ToString());

        
return returnValue;
    }

}

posted on 2008-08-27 16:54  朱胜  阅读(271)  评论(0编辑  收藏  举报