基于 Transaction 类的分布式显式事务
自.NET2.0以来增加了System.Transactions命名空间,为.NET应用程序带来了一个新的事务编程模型。
这个命名空间提供了几个依赖的TransactionXXX类。Transaction是所有事务处理类的基类,并且定义了所有事务类都可以使用的属性、方法和事件。CommittableTransaction是唯一个支持提交的事务类,这个类有一个Commit()方法,所有其他事务类都只能执行回滚。
本文将通过银行转账的示例介绍基于 Transaction 类的分布式显式事务的用法。
在MySql中建立如下表:

注意Balance是无符号的decimal类型(如下图)

插入测试数据:
(转账成功的测试数据):

(转账失败的测试数据):

示例代码:
(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(Transaction transaction,string sql,params MySqlParameter[] parameters)
{
int result = -1;
using (MySqlConnection conn = new MySqlConnection(GetConnection()))
{
conn.Open();
if (null != transaction)
{
conn.EnlistTransaction(transaction); //将连接登记到事务
}
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(Transaction transaction)
{
string sql = @"UPDATE bankaccountn SET UserName = @UserName,Balance = @Balance
WHERE BankaccountnId= @BankaccountnId;";
return SqlHelper.ExecuteNonQuery(transaction, sql, new MySqlParameter("@BankaccountnId", this.bankaccountnId), new MySqlParameter("@UserName", this.UserName), new MySqlParameter("@Balance", this.Balance));
}
#region 支出 + Epend(Transaction transaction, decimal money)
public void Epend(Transaction transaction, decimal money)
{
this.Balance -= money;
this.Update(transaction);
}
#endregion
#region 收入 + Income(Transaction transaction, decimal money)
public void Income(Transaction transaction, decimal money)
{
this.Balance += money;
this.Update(transaction);
}
#endregion
public bool TransferOfAccount(string incomeBankaccountnId, decimal money)
{
using (var transaction = new CommittableTransaction())
{
try
{
Bankaccountn incomeBankaccountn = new Bankaccountn(incomeBankaccountnId);
incomeBankaccountn.Income(transaction, money); //收款账户入账
this.Epend(transaction, money); //付款账户支出
transaction.Commit();
return true;
}
catch
{
transaction.Rollback();
//这里写做异常信息的记录的代码
return false;
}
}
}
}
}
(3)测试代码
Bankaccountn one = new Bankaccountn("6666660123456789");
if (one.TransferOfAccount("6666669876543210", 200M))
{
Response.Write("<script>alert('转账成功')</script>");
}
else
{
Response.Write("<script>alert('转账失败')</script>");
}
代码分析:
创建基于 Transaction 类的分布式显式事务步骤如下:
1)实例化一个可提交的CommittableTransaction对象;
2)将要参与事务的连接通过MySqlConnection对象的EnlistTransaction(Transaction transaction)登记到上一步创建的CommittableTransaction对象上;
3)如果事务可以成功完成,使用CommittableTransaction对象的Commit()方法提交事务处理结果;
4)如果事务处理中发生错误,就调用CommittableTransaction对象的Rollback()方法,撤销每一个修改。
这样分析下来是不是和上一节的ADO.NET事务一样简单?
基于 Transaction 类的分布式显式事务的更多相关文章
- 基于TransactionScope类的分布式隐式事务
System.Transactions 命名空间中除了上一节中提到的基于 Transaction 类的显式编程模型,还提供使用 TransactionScope 类的隐式编程模型,它与显示编程模型相比 ...
- SQLServer之创建显式事务
显式事务定义 显式事务以 BEGIN TRANSACTION 语句开始,并以 COMMIT 或 ROLLBACK 语句结束. 备注 BEGIN TRANSACTION 使 @@TRANCOUNT 按 ...
- (4.19)sql server中的事务模式(隐式事务,显式事务,自动提交事务)
(4.19)sql server中的事务模式(隐式事务,显式事务,自动提交事务) 1.概念:隐式事务,显式事务,自动提交事务 2.操作:如何设置事务模式 3.存储过程中的事务 XACT_ABORT 1 ...
- SQL Server显式事务与隐式事务
事务是单个的工作单元.如果某一事务成功,则在该事务中进行的所有数据修改均会提交,成为数据库中的永久组成部分.如果事务遇到错误且必须取消或回滚,则所有数据库修改均被清除. SQL Server中有一下几 ...
- SpringBoot显式事务
参考:https://www.jianshu.com/p/f5fc14bde8a0 后续测试代码的完整项目:https://files.cnblogs.com/files/hellohello/dem ...
- C++ 不具有继承关系的类之间的显式,隐式转换 2013-07-11 15:41
好久没有写blog了,今天在学习c#的时候看到某一章节 讲类的隐式与显式转换.特此留笔,以供后续参考之用. 关于显式,隐式转换有些争论,说什么不建议隐式转换.但是个人认为非必要,如果有良好的基础书写基 ...
- QT创建与调用Dll方法(包括类成员)--显式调用
看网上的好多关于QT调用Dll的方法,大部分都是调用函数的,并没有调用C++类成员的情况,即使是有,比如说: 使用Qt编写模块化插件式应用程序 Qt 一步一步实现dll调用(附源码)---(这一篇里没 ...
- SQL Server Insert时开启显式事务
如果没法避免一条一条的写入,那么在处理前显示开启一个事务 begin tran 在处理完成后 commit 这样也要比不开显示事务会快很多! while i < 10000begin inse ...
- CALayer的隐式动画和显式动画
隐式事务 任何对于CALayer属性的修改,都是隐式事务,都会有动画效果.这样的事务会在run-loop中被提交. - (void)viewDidLoad { //初始化一个layer,添加到主视图 ...
随机推荐
- 世纪互联提供的关于Powershell中将虚拟机加入备份保管库的方法
请您参考以下步骤进行操作,如有问题请与我们联系: 对一台ARM虚拟机(虚拟机名称:paularm08r21)进行备份(参考:https://www.azure.cn/documentation/art ...
- jstat 使用日志
如何判断JVM是否存在内存问题呢?如何判断JVM垃圾回收是否正常?一般的top指令基本上满足不了这样的需求,因为它主要监控的是总体的系统资源,很难定位到java应用程序. Jstat是JDK自带的一个 ...
- pyqt、webkit和qt之间的关系
前言 最近在维护一个PYQT的项目,有很多不明白的地方,总结一下,共其他直接使用pyqt的人参考一下.PyQT是一个生成图形应用程序的工具包.是python语言和成功的Qt库的绑定.Qt库是这个世界上 ...
- top命令参数
参数说明 d 指定每两次屏幕信息刷新之间的时间间隔.当然用户可以使用s交互命令来改变之. p 通过指定监控进程ID来仅仅监控某个进程的状态. q该选项将使top没有任何延迟的进行刷新.如果调用程序有超 ...
- 在openerp撰写消息中增加图片
openerp的撰写消息中, 在文本输入框中, 具有设置文本字体,设置对齐方式 等多种功能, 就像像写这篇新浪blog一样, 可以输入富文本信息. 美中不足的是, 它不能插入图片. 我们如何才能让op ...
- spring & java 面试
https://blog.csdn.net/u014079773/article/details/52453002 1.Spring中AOP的应用场景.Aop原理.好处? 答:AOP--Aspect ...
- gitlab webhook报500
使用root登陆gitlab,进入如下位置:
- uml中活动图与流程图的区别
活动图定义: 活动图是UML用于对系统的动态行为建模的另一种常用工具,它描述活动的顺序,展现从一个活动到另一个活动的控制流.活动图在本质上是一种流程图. 它是UML中用于对系统动态活动建模的图形,反映 ...
- Cecos国内集成系统基于rhel6.5
整体上,secos对云.虚拟化.等整体的解决方案(一键打包),很不错.做出了有益的探索.... 本次测试基于版本测试,不得说官方文档也是挺全的,很好!!!! CecOS-1.4.2-Final-170 ...
- Java实现多线程的四种实现方式
以计算0到1000之间的和为例 import java.util.ArrayList; import java.util.LinkedList; import java.util.List; impo ...