• 分布式事物嵌套事物


    1.内部事物 需 using (TransactionScope scope = new TransactionScope(TransactionScopeOption.RequiresNew))  否则会出现“已终止事物” 的错误

    TransactionScope 分布式事务的使用案例 以及简单说明

     TransactionScope 是的.net Framework2.0版本中增加的一个新命名空间。他的用途是为数据库访问提供一个“轻量级”的事物。使用之前必须添加对 System.Transactions.dll 的引用。先介绍介绍几个简单的参数。

    TransactionScopeOptions 描述
    Required 如果已经存在一个事务,那么这个事务范围将加入已有的事务。否则,它将创建自己的事务。
    RequiresNew 这个事务范围将创建自己的事务。
    Suppress 如果处于当前活动事务范围内,那么这个事务范围既不会加入氛围事务 (ambient transaction),也不会创建自己的事务。当部分代码需要留在事务外部时,可以使用该选项。

    您可以在代码的任何位置上随是查看是否存在事务范围,具体方法就是查看 System.Transactions.Transaction.Current 属性。如果这个属性为“null”,说明不存在当前事务。
           若要更改 TransactionScope 类的默认设置,您可以创建一个 TransactionOptions 对象,然后通过它在 TransactionScope 对象上设置隔离级别和事务的超时时间。TransactionOptions 类有一个 IsolationLevel 属性,通过这个属性可以更改隔离级别,例如从默认的可序列化 (Serializable) 改为ReadCommitted,甚至可以改为 SQL Server 2005 引入的新的快照 (Snapshot) 级别。(请记住,隔离级别仅仅是一个建议。大多数数据库引擎会试着使用建议的隔离级别,但也可能选择其他级别。)此 外,TransactionOptions 类还有一个 TimeOut 属性,这个属性可以用来更改超时时间(默认设置为 1 分钟)。
    TransactionOptions opt= new TransactionOptions();
    //设置TransactionOptions

    opt.IsolationLevel = IsolationLevel.ReadCommitted;
    // 设置超时间隔为2分钟,默认为60秒
    opt.Timeout = new TimeSpan(0, 2, 0);

    使用时候将

    using (TransactionScope sCope = new TransactionScope(TransactionScopeOption.RequiresNew, opt))

    其他和默认一样

    下面做一个简单的demo 只需要添加很少的几行代码,这个模型可以对异常进行处理,执行结束后会自行清理,此外,它还可以对命令的提交或回滚进行管理

    1.TransactionScope  在一个事务范围内

    在app.config中

    <connectionStrings>
        <add name="myCon" connectionString="Data Source=.;uid=sa;pwd=sa;database=B2C3;Asynchronous Processing=true"/>
        <add name="myCon2" connectionString="Data Source=.;uid=sa;pwd=sa;database=b2c;Asynchronous Processing=true"/>
        <add name="myCon3" connectionString="Data Source=.;uid=sa;pwd=sa;database=demo;Asynchronous Processing=true"/>
        <add name="myCon4" connectionString="Data Source=.;uid=sa;pwd=sa;database=News;Asynchronous Processing=true"/>


      </connectionStrings>

     static void Main(string[] args)
            {
               string constr = ConfigurationManager.ConnectionStrings["myCon"].ConnectionString;
                string constr2 = ConfigurationManager.ConnectionStrings["myCon2"].ConnectionString;
                string sql = "insert into [Tuser](username,pwd,age) values('新闻socpe测试','bbb',10)";
                #region 不同库的事务
                using (TransactionScope sope = new TransactionScope())
                {

                     using(SqlConnection con =new SqlConnection(constr))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql, con))
                        {
                            con.Open();
                          int a=  cmd.ExecuteNonQuery();
                          Console.WriteLine(a);
                       
                        }
                      
                   
                    }
                    using (SqlConnection con = new SqlConnection(constr2))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql, con))
                        {
                            con.Open();
                            int b = cmd.ExecuteNonQuery();
                            Console.WriteLine(b);

                        }


                    }

                    addOtherUser();
                    sope.Complete();

                }
                #endregion

        sope.Complete(); 是个标示。只有全部运行才提交事务

    2.嵌套 调用事务

            static void Main(string[] args)
            {


                string constr = ConfigurationManager.ConnectionStrings["myCon"].ConnectionString;
                string constr2 = ConfigurationManager.ConnectionStrings["myCon2"].ConnectionString;
                string sql = "insert into [Tuser](username,pwd,age) values('新闻socpe测试','bbb',10)";
                #region 不同库的事务
                using (TransactionScope sope = new TransactionScope(TransactionScopeOption.Required))
                {

                
                    using(SqlConnection con =new SqlConnection(constr))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql, con))
                        {
                            con.Open();
                          int a=  cmd.ExecuteNonQuery();
                          Console.WriteLine(a);
                       
                        }
                      
                   
                    }
                    using (SqlConnection con = new SqlConnection(constr2))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql, con))
                        {
                            con.Open();
                            int b = cmd.ExecuteNonQuery();
                            Console.WriteLine(b);

                        }


                    }

                    addOtherUser();
                    sope.Complete();

                }
                #endregion


            }

            private static void addOtherUser()
            {
                string constr3 = ConfigurationManager.ConnectionStrings["myCon3"].ConnectionString;
                string constr4 = ConfigurationManager.ConnectionStrings["myCon4"].ConnectionString;
                string sql1 = "insert into [hr_user](username,password) values('新闻socpe测试','bbb')";
                string sql2 = "insert into [Users](username,userpwd) values('新闻socpe测试','bbb')";

                //RequiresNew 这个事务范围将创建自己的事务。
                using(TransactionScope sope=new TransactionScope(TransactionScopeOption.RequiresNew))
                {

                    using (SqlConnection con = new SqlConnection(constr3))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql1, con))
                        {
                            con.Open();
                            int a = cmd.ExecuteNonQuery();
                            Console.WriteLine(a);

                        }


                    }
                    using (SqlConnection con = new SqlConnection(constr4))
                    {
                        using (SqlCommand cmd = new SqlCommand(sql2, con))
                        {
                            con.Open();
                            int b = cmd.ExecuteNonQuery();
                            Console.WriteLine(b);

                        }


                    }
                    sope.Complete();
                }
           
            }

     总结:

    现在知道了TransactionScope中的数据库操作实际是参与了其中的环境事务,将它理解为是自动建立的SqlTransaction,而嵌套在其中的TransactionScope中的数据库操作会添加到这个环境事务中(以TransactionScopeOption.Required为参数生成的TransactionScope)。

      也知道了Complete方法并不是执行后,就会提交事务,而只是表明之前的动作都符合要求,只是一种确认,不执行该方法,事务便不能完成。而 只有最外层TransactionScope执行了Complete方法后,在离开using块时,事务才真正的提交。所以说 TransactionScope是能嵌套的。

      Transaction类有一静态属性Current,在一个TransactionScope中的Complete方法执行之前可以访问,它返回的便是环境事务。

    但是:   进入和退出事务都要快,这一点非常重要,因为事务会锁定宝贵的资源。最佳实践要求我们在需要使用事务之前再去创建它,在需要对其执行命令前迅速打开连接, 执行动作查询 (Action Query),并尽可能快地完成和释放事务。在事务执行期间,您还应该避免执行任何不必要的、与数据库无关的代码,这能够防止资源被毫无疑义地锁定过长的 时间


            }

  • 相关阅读:
    BZOJ 3881: [Coci2015]Divljak
    BZOJ 2434: [Noi2011]阿狸的打字机
    BZOJ 2580: [Usaco2012 Jan]Video Game
    BZOJ 3940: [Usaco2015 Feb]Censoring
    BZOJ 3942: [Usaco2015 Feb]Censoring
    PTA L2-002 链表去重 团体程序设计天梯赛-练习集
    PTA L2-001 紧急救援-最短路(Dijkstra)多条最短路找最优解并输出路径 团体程序设计天梯赛-练习集
    PTA L1-020 帅到没朋友 团体程序设计天梯赛-练习集
    Codeforces 429 B. Working out-dp( Codeforces Round #245 (Div. 1))
    HDU 6467.简单数学题-数学题 (“字节跳动-文远知行杯”广东工业大学第十四届程序设计竞赛)
  • 原文地址:https://www.cnblogs.com/tiancai/p/5416399.html
Copyright © 2020-2023  润新知