自.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 类的分布式显式事务的更多相关文章

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

    System.Transactions 命名空间中除了上一节中提到的基于 Transaction 类的显式编程模型,还提供使用 TransactionScope 类的隐式编程模型,它与显示编程模型相比 ...

  2. SQLServer之创建显式事务

    显式事务定义 显式事务以 BEGIN TRANSACTION 语句开始,并以 COMMIT 或 ROLLBACK 语句结束. 备注 BEGIN TRANSACTION 使 @@TRANCOUNT 按 ...

  3. (4.19)sql server中的事务模式(隐式事务,显式事务,自动提交事务)

    (4.19)sql server中的事务模式(隐式事务,显式事务,自动提交事务) 1.概念:隐式事务,显式事务,自动提交事务 2.操作:如何设置事务模式 3.存储过程中的事务 XACT_ABORT 1 ...

  4. SQL Server显式事务与隐式事务

    事务是单个的工作单元.如果某一事务成功,则在该事务中进行的所有数据修改均会提交,成为数据库中的永久组成部分.如果事务遇到错误且必须取消或回滚,则所有数据库修改均被清除. SQL Server中有一下几 ...

  5. SpringBoot显式事务

    参考:https://www.jianshu.com/p/f5fc14bde8a0 后续测试代码的完整项目:https://files.cnblogs.com/files/hellohello/dem ...

  6. C++ 不具有继承关系的类之间的显式,隐式转换 2013-07-11 15:41

    好久没有写blog了,今天在学习c#的时候看到某一章节 讲类的隐式与显式转换.特此留笔,以供后续参考之用. 关于显式,隐式转换有些争论,说什么不建议隐式转换.但是个人认为非必要,如果有良好的基础书写基 ...

  7. QT创建与调用Dll方法(包括类成员)--显式调用

    看网上的好多关于QT调用Dll的方法,大部分都是调用函数的,并没有调用C++类成员的情况,即使是有,比如说: 使用Qt编写模块化插件式应用程序 Qt 一步一步实现dll调用(附源码)---(这一篇里没 ...

  8. SQL Server Insert时开启显式事务

    如果没法避免一条一条的写入,那么在处理前显示开启一个事务 begin tran  在处理完成后 commit 这样也要比不开显示事务会快很多! while i < 10000begin inse ...

  9. CALayer的隐式动画和显式动画

    隐式事务 任何对于CALayer属性的修改,都是隐式事务,都会有动画效果.这样的事务会在run-loop中被提交. - (void)viewDidLoad { //初始化一个layer,添加到主视图 ...

随机推荐

  1. ZH奶酪:LAMP环境中如何重新部署一个Yii2.0 web项目

    使用Yii2.0 framework开发的项目,使用Github进行版本控制,现在要把这个项目部署到一个新的电脑/系统中: (1)安装LAMP (2)在/var/www/html目录下执行 git c ...

  2. 【Ubuntu】Ubuntu bug “Reached target Shutdown”

    在使用 Ubuntu-16.04.3-server-amd64.iso 版本(参考官方,iso下载地址)的时候,遇到一个Ubuntu的Bug,后来查了一下,在官方看到,目前还是Unassigned: ...

  3. APP测试体系

    网上找的图片,总结的很好:

  4. VMware虛擬化技術實作問答

    http://www.netadmin.com.tw/article_content.aspx?sn=1202130002&ns=1203280001&jump=3 Q4:啟用VMwa ...

  5. Linux内核配置.config文件

    在命令行中,进入顶层内核目录,并输入命令make menuconfig,就可以启动一个基于菜单的内核配置编辑器.从这里开始,你可以访问每个可用的配置参数,并生成一个定制的内核配置. 当你退出配置编辑器 ...

  6. 用Eclipse进行远程Debug代码 (转)

    来自:http://blog.csdn.net/fyq891014/article/details/7534711 首先你本地Eclipse上要有和部署在远程服务器一至的项目,否则debug的时候会出 ...

  7. SSM项目的数据库密码加密方案

    项目主要采用:SpringMVC4.3.2.RELEASE +Spring4.3.2.RELEASE + Maven 3.3.3 + druid 1.0.29 + Mybatis 3.2.8 + My ...

  8. MySQL查看当前用户、存储引擎、日志

    #查看MySQL的当前用户 mysql> SELECT USER(); +----------------+ | USER() | +----------------+ | root@local ...

  9. Android实训案例(七)——四大组件之中的一个Service初步了解,实现通话录音功能,抽调接口

    Service Service的奇妙之处.在于他不须要界面,一切的操作都在后台操作,所以非常多全局性(手机助手,语音助手)之类的应用非常长须要这个.我们今天也来玩玩 我们新建一个project--Se ...

  10. IIS 管理器无法验证此内置帐户是否有访问权

    解决办法:1.打开iss管理器2.点击网站——localhost3.点击右上角位置的"基本设置"——"链接为"——"特定用户"——" ...