基于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类的分布式隐式事务相关推荐
- 在.net 2.0 中执行分布式事务:隐式事务篇(SQL Server 与 Oracle)
项目涉及到多个数据库的查询更新操作,也就必然需要分布式事务的支持,查了MSDN知道 .net 2.0 中利用新增的 System.Transactions 命名空间可以简单的实现分布式事务: Syst ...
- 基础才是重中之重~.net中的显式事务与隐式事务
回到目录 .net中的事务可以分为显式的和稳式的,显式的就是说需要我们手动去指定事务的提交和回滚,而稳式的是.net帮助我们进行管理的,当你的事务代码段没有发生异常时,它会帮助我们进行提交,反之,进行 ...
- C++拾趣——类构造函数的隐式转换
之前看过一些批判C++的文章,大致意思是它包含了太多的"奇技淫巧",并不是一门好的语言.我对这个"奇技淫巧"的描述颇感兴趣,因为按照批判者的说法,C++的一些特 ...
- Scala _09样例类(case classes)隐式转换
样例类(case classes) 概念理解 使用了case关键字的类定义就是样例类(case classes),样例类是种特殊的类.实现了类构造参数的getter方法(构造参数默认被声明为val), ...
- 关于类类型的隐式类型转换
1.若构造函数只接受一个实参,则它实际上定义了转换为此类类型的隐式转换机制,这种构造函数又称作转换构造函数. 2.能通过一个实参调用的构造函数定义了该参数类型向类类型隐式转换的规则.也就是说,若定义了 ...
- 【源码】基于非线性Newmark方法的隐式动态求解器
求解函数 function Result=Newmark_Nonlinear(Elements,Material,Support,Free,M,C,f,fs,delta) Input Elements ...
- scala中的隐式转换、隐式参数和隐式类
scala中的隐式转换.隐式参数和隐式类 @(SCALA)[scala] scala中的隐式转换隐式参数和隐式类 一隐式转换 1示例 2隐式转换的条件 二隐式参数 1示例 三隐式类 1示例 隐式转换是 ...
- C语言隐式/显式类型转换 | C++四种强制类型转换、类的隐式转换、explicit
文章目录 C语言类型转换 隐式类型转换 显式类型转换 C++ 强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast 类的隐式类型转换 ...
- C++隐式类类型转换
C++可以定义如何将其他类型的对象隐式转换为我们的类类型或将我们的类类型的对象隐式转换为其他类型.为了定义到类类型的隐式转换,需要定义合适的构造函数. 说明:可以用单个实参来调用的构造函数定义了从形参 ...
最新文章
- JavaScript校验身份证,包含省份、长度、出生年月日、校验位的检测、性别、年龄...
- Rating Methodology – Bank Loan / Facility Rating(CRISL)
- iOS开发之窗口和视图
- 单片机知识点总结框图_单片机原理及应用期末考试必考知识点重点总结
- C#LeetCode刷题之#860-柠檬水找零(Lemonade Change)
- 表格无边框,有内框,在table嵌套时,防止出现重复边线
- homebrew安装及常用命令
- 如何使用js判断视频是否可以成功访问
- python2.7 安装第三方库
- 使用易宝支付接口实现java网上支付功能。
- java格斗代码_java学习2打架代码编写
- win10 开机自动启动脚本
- 使用regedit导入导出环境变量
- win7(64位)+vs2010+orge1.8.1
- RocketMQ实战2
- 【SAP Basis】SAP用户账号管理
- OpenCV3 和 Qt5 计算机视觉:1~5
- edge浏览器打开html文件路径被拆分,Win10默认浏览器被强制修改为Edge的两种解决方法...
- Arduino温度传感器全系列使用详解
- 敏捷史话(四):敏捷是人的天性 —— Arie van Bennekum
热门文章
- BuildSql增加了【生成数据库文档】的功能了
- ios 折线图_《解神者》ios和安卓互通吗 ios和安卓互通分析
- layui 横向表单_对layui中表单元素的使用详解
- oracle数据库 pc6,使用logdump 查看ogg的CSN
- 内核aio_Java面试题BIO、NIO、AIO有什么区别?
- 向上累积频数怎么算_天天向上:王一博单人cut只有7分钟,给了高天鹤最后的疼爱...
- BZOJ 2144 跳跳棋(神仙建模题,倍增 LCA,二分)【BZOJ修复工程】
- luogu P4745 [CERC2017]Gambling Guide(期望DP + 最短路实现)
- luogu P2596 [ZJOI2006]书架(平衡树、无旋treap(按排名分裂)一些更复杂的操作)
- php smarty csv,6个smarty小技巧