zoukankan      html  css  js  c++  java
  • 一次提交涉及两个数据库处理

    业务场景:用户下单à付款à扣减库存

    问题:当付款成功,扣减库存失败,如何处理。是否可以将这两个事务放在一个Transaction中处理?

       

       

    一、基本概念(Transaction)

    什么是事务?事务很任性,只接受成功或失败。在事务包括的范围内,所有操作都是不可分割的单元,当所有操作都成功后事务才算执行成功,否则将进行回滚操作。回忆一下课本中的ACID四大属性(了解即可,复制了书中的描述):

    A(Atomicity)原子性:不可再分割的整体,事务中的含义是所有操作都被视为同一不可分割的整体,要么都成功要么都失败。

    C(Consistence)一致性:事务开始前和事务结束后,数据库的完整性约束没有被破坏。

    I(Isolation)隔离性:当数据正处于事务中时是独占的,不能被其它应用所访问,确保不会读取到脏数据。

    D(Durability)持久性:事务一旦提交,则物理存储于数据库中,且在下一次操作前,数据的状态不会被改变。

    二、解决方案

    通过System.TransactionScope 可以实现两个库之间的事务,我们只需要引入System.Transactions.dll 就可以微软提供的强大事务功能了。这里实现的是两个数据库之间的整务,若是要实现数据库和NTFS文件之间的事务,请大家搜索DTC机制,来实现非数据库之间的事务。这部分内容我也正在实践和学习,待理解以后再发出博文与大家探讨。

    本实例是连接了本机的两个数据库服务SQLServer2008R2和MySQL,所以需要在工程中引入MySQL.dll。

     以下是实现代码,当DoPayment方法执行成功后,Dostock方法执行失败,此时事务不执行transcope.Complete();语句,在SQLServer中的数据会被回滚。并且在执行Dostock方法时,去查询SQLServer中是查询不到数据的。

    namespace ConsoleApplication3
    {
        class Program
        {
            static string SQLConStr = "server=10.10.60.195,1433;database=tmp;uid=sa;pwd=sa;";
            static string MySQLConStr = "server=localhost;uid=root;pwd=root;database=test";
            static void Main(string[] args)
            {
                OrderLogic();
            }
    
            public static void OrderLogic()
            {
                using (TransactionScope transcope = new TransactionScope())
                {
                    //用户付款
                    //向SQLServer.TPayment表插入一条记录
                    string sqlText = "insert into TPayment values(156,1,1)";
                    DoPayment(sqlText);
    
                    //扣减库存
                    //更新MySQL.Product表中stocknum字段
                    string mysqlText = "update Product set stocknum=stocknum-5 where id=1";
                    DoStock(mysqlText);
    
                    transcope.Complete();
                }
            }
    
            public static void DoPayment(string sqlText)
            {
                SqlConnection conn = null;
                SqlCommand com = null;
    
                try
                {
                    conn = new SqlConnection(SQLConStr);
                    conn.Open();
    
                    com = new SqlCommand(sqlText, conn);
                    com.ExecuteNonQuery();
                }
                catch
                {
    
                }
                finally
                {
                    if (com != null)
                        com.Dispose();
                    if (conn != null)
                        conn.Close();
                }
            }
    
            public static void DoStock(string sqlText)
            {
                MySqlConnection conn = null;
                MySqlCommand com = null;
    
                try
                {
                    conn = new MySqlConnection(MySQLConStr);
                    conn.Open();
    
                    com = new MySqlCommand(sqlText, conn);
                    com.ExecuteNonQuery();
                }
                catch
                {
    
                }
                finally
                {
                    if (com != null)
                        com.Dispose();
                    if (conn != null)
                        conn.Close();
                }
            }
        }
    }
    如果觉得喜欢本文或对您有帮助,请记得点推荐哟!
    作 者 :zhouxy
    邮 箱 :799791187@qq.com
    本文版权归作者和博客园共有,欢迎转载,但须保留此声明,且在文章页面明显位置给出原文连接。
    如果本文有什么不妥或者错误的地方,请您一定要在评论中指出,我会及时查明并修正!非常感谢您的不吝赐教!
  • 相关阅读:
    IntentService源码分析
    startService过程源码分析
    洛谷P3300 城市规划
    agc033
    洛谷P3306 随机数生成器
    洛谷P3299 保护出题人
    洛谷P3298 泉
    洛谷P3296 刺客信条
    树hash
    我们都爱膜您退火!
  • 原文地址:https://www.cnblogs.com/vinzhou/p/4365460.html
Copyright © 2011-2022 走看看