经常遇到在三层架构中使用事务,而逻辑层无法使用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;
}
}