首页 > 代码库 > 基于TransactionScope类的分布式隐式事务

基于TransactionScope类的分布式隐式事务

  System.Transactions 命名空间中除了上一节中提到的基于 Transaction 类的显式编程模型,还提供使用 TransactionScope 类的隐式编程模型,它与显示编程模型相比,更加方便简单,它也是MSDN中建议使用的编程模型。
  下面,我们基于TransactionScope类实现上一节银行转帐的例程。
  示例代码:
  (1)SqlHelper.cs
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using System.Configuration;
  using MySql.Data.MySqlClient;
  using System.Transactions;
  using System.Data;
  namespace 事务处理
  {
  public class SqlHelper
  {
  public static string GetConnection()
  {
  string connStr = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
  return connStr;
  }
  public static int ExecuteNonQuery(string sql, params MySqlParameter[] parameters)
  {
  int result = -1;
  using (MySqlConnection conn = new MySqlConnection(GetConnection()))
  {
  conn.Open();
  using (MySqlCommand cmd = conn.CreateCommand())
  {
  cmd.CommandText = sql;
  cmd.Parameters.AddRange(parameters);
  result = cmd.ExecuteNonQuery();
  }
  }
  return result;
  }
  public static DataTable ExecuteDataTable(string sql, params MySqlParameter[] parameters)
  {
  using (MySqlConnection conn = new MySqlConnection(GetConnection()))
  {
  using (MySqlCommand cmd = conn.CreateCommand())
  {
  cmd.CommandText = sql;
  cmd.Parameters.AddRange(parameters);
  using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
  {
  using (DataSet ds = new DataSet())
  {
  da.Fill(ds);
  return ds.Tables[0];
  }
  }
  }
  }
  }
  }
  }
  (2)Bankaccountn.cs
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Web;
  using MySql.Data.MySqlClient;
  using System.Data;
  using System.Transactions;
  namespace 事务处理
  {
  public class Bankaccountn
  {
  public Bankaccountn(string bankaccountnId)
  {
  string sql = @"SELECT * FROM Bankaccountn WHERE BankaccountnId=@BankaccountnId;";
  DataTable dt = SqlHelper.ExecuteDataTable(sql, new MySqlParameter("@BankaccountnId", bankaccountnId));
  if (dt.Rows.Count <= 0)
  {
  throw new Exception("账户不存在!");
  }
  else if (dt.Rows.Count > 1)
  {
  throw new Exception("异常信息:有重名的账户存在!");
  }
  else
  {
  this.bankaccountnId = dt.Rows[0]["BankaccountnId"] as string;
  this.UserName = dt.Rows[0]["UserName"] as string;
  this.Balance = Convert.ToDecimal(dt.Rows[0]["Balance"]);
  }
  }
  private string bankaccountnId;
  public string UserName
  {
  get;
  private set;
  }
  public decimal Balance
  {
  get;
  private set;
  }
  protected int Update()
  {
  string sql = @"UPDATE bankaccountn SET UserName = @UserName,Balance = @Balance
  WHERE BankaccountnId= @BankaccountnId;";
  return SqlHelper.ExecuteNonQuery(sql, new MySqlParameter("@BankaccountnId", this.bankaccountnId), new MySqlParameter("@UserName", this.UserName), new MySqlParameter("@Balance", this.Balance));
  }
  public void Epend( decimal money)
  {
  this.Balance -= money;
  this.Update();
  }
  public void Income(decimal money)
  {
  this.Balance += money;
  this.Update();
  }
  public bool HiddenTransferOfAccount(string incomeBankaccountnId, decimal money)
  {
  bool result = true;
  using (TransactionScope scope = new TransactionScope())
  {
  try
  {
  Bankaccountn incomeBankaccountn = new Bankaccountn(incomeBankaccountnId);
  incomeBankaccountn.Income(money); //收款账户入账
  this.Epend(money); //付款账户支出
  scope.Complete();
  }
  catch (Exception ex)
  {
  //这里写做异常信息的记录的代码
  result = false;
  }
  }
  return result;
  }
  }
  }
  (3)测试代码
  Bankaccountn one = new Bankaccountn("6666660123456789");
  if (one.HiddenTransferOfAccount("6666669876543210", 200M))
  {
  Response.Write("<script>alert(‘转账成功‘)</script>");
  }
  else
  {
  Response.Write("<script>alert(‘转账失败‘)</script>");
  }
  代码分析:
  使用TransactionScope 之后,事务管理器会 预执行代码,直至Complete()处,如果过程没有出错,这通知事务管理器去提交,如果错误就不提交,保证了整个执行过程的一致性。
  但,在使用隐式编程模型时应注意以下几点:托福答案
  1)要确保参与事务的资源(如连接的打开等)的全登记放在TransactionScope 实例化对象之后,调用Complete()方法之前。
  2)从TransactionScope 实例化到调用Complete()方法之间的代码,不要吃掉异常。
  using (TransactionScope scope = new TransactionScope())
  {
  try
  {
  //要确保参与事务的资源全部登记在这个位置(如连接的打开等)
  Bankaccountn incomeBankaccountn = new Bankaccountn(incomeBankaccountnId);
  incomeBankaccountn.Income(money); //收款账户入账
  this.Epend(money); //付款账户支出
  scope.Complete();
  }
  { catch (Exception ex)
  //捕获异常要在这个位置
  result = false;
  }
  }

基于TransactionScope类的分布式隐式事务