System. in addition to the explicit Programming Model Based on the Transaction class mentioned in the previous section, the Transactions namespace also provides an implicit programming model using the TransactionScope class, which is more convenient and simple than the display programming model, it is also a recommended programming model in MSDN.
Next, we implement the previous bank transfer routine Based on the TransactionScope class.
Sample Code:
(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 Transaction Processing
{
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 Transaction Processing
{
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 ("the account does not exist! ");
}
else if (dt.Rows.Count > 1)
{
Throw new Exception ("Exception message: an account with duplicate names exists! ");
}
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); // The receiving account is recorded.
This. Epend (money); // payment account expenditure
scope.Complete();
}
catch (Exception ex)
{
// Code for recording exception information
result = false;
}
}
return result;
}
}
}
(3) test code
Bankaccountn one = new Bankaccountn("6666660123456789");
if (one.HiddenTransferOfAccount("6666669876543210", 200M))
{
Response. Write ("<script> alert ('transfer successful ') </script> ");
}
else
{
Response. Write ("<script> alert ('transfer failed') </script> ");
}
Code Analysis:
After TransactionScope is used, the transaction manager will pre-execute the code until the Complete (). If there is no error in the process, the transaction manager will be notified to submit the code. if the error is not reported, ensures the consistency of the entire execution process.
Note the following when using an implicit programming model:
1) ensure that the full registration of the resources involved in the transaction (such as the opening of the connection) is placed after the TransactionScope instantiates the object and before the Complete () method is called.
2) do not eat the exception from the TransactionScope Instantiation to the code that calls the Complete () method.
using (TransactionScope scope = new TransactionScope())
{
try
{
// Make sure that all resources involved in the transaction are registered at this location (such as opening a connection)
Bankaccountn incomeBankaccountn = new Bankaccountn(incomeBankaccountnId);
IncomeBankaccountn. Income (money); // The receiving account is recorded.
This. Epend (money); // payment account expenditure
scope.Complete();
}
catch (Exception ex)
{
// Capture exceptions at this location
result = false;
}
}