下面,我們基于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("<scr}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;}}
新聞熱點
疑難解答