zoukankan      html  css  js  c++  java
  • 基于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;
        }
    }

  • 相关阅读:
    记一次性能优化经历
    把一个一中的字段更新另一个表中的t-sql
    Dapper 中使用sql in 关键字查询
    HTML5 学习笔记 应用程序缓存
    HTML5学习笔记 Web存储
    HTML5 学习笔记 表单属性
    HTML5学习笔记 Geolocation(地理定位)
    vim插件之delimitMate.vim
    vim 插件之 surround.vim
    vim 脚本之快速打印log
  • 原文地址:https://www.cnblogs.com/hanzhaoxin/p/3751732.html
Copyright © 2011-2022 走看看