none
分布式事务TransactionScope不能提交的问题 RRS feed

  • 问题

  • using (TransactionScope ts = new TransactionScope())
            {
                string conns = ConfigurationManager.AppSettings["ConnString"].ToString();
                try
                {
                    using (SqlConnection conn = new SqlConnection(conns))
                    {
                        conn.Open();
                        SqlCommand com = conn.CreateCommand();
                        com.CommandText = "update users set name='tt' where id=2";
                        com.ExecuteNonQuery();
                        com.CommandText = "update userds set name='tt' where id=1";
                        com.ExecuteNonQuery();
                       
                    }
                    ts.Complete();
                }
                catch (Exception ex)
                {
                    string dd = ex.Message;
                }
                //ts.Complete();
            }

    我的代码是这样的,当ts.Complete();放到Try里的时候,事务是没问题的,但当放到Try外面的时候,就是我注释的地方,发现事务失败了,第一条语句执行成功并插入修改了数据库。
    请帮忙,多谢
    2010年1月13日 8:37

答案

  • 你好!
         这里文档写的有些问题,我已经在你的另外一个帖子中做了回复:
    把try...catch放在using (TransactionScope scope = new TransactionScope())外面!
    或是保存原来的逻辑,但是在catch中重新抛出异常!
    周雪峰
    • 已标记为答案 YiChun Chen 2010年1月14日 10:06
    2010年1月13日 10:46
    版主
  • 你好!

    这个示例的确是的问题的,这里我再补充说明一下 TransactionScope 运行的基本逻辑,希望能帮助你更好的理解使用它。

    try
    {
        using (TransactionScope ts = new TransactionScope()) // 01 声明实例的同时开启事务
        {
            string conns = ConfigurationManager.AppSettings["ConnString"].ToString();
    
            using (SqlConnection conn = new SqlConnection(conns))
            {
                conn.Open();
                SqlCommand com = conn.CreateCommand();
                com.CommandText = "update users set name='tt' where id=2";
                com.ExecuteNonQuery();
                com.CommandText = "update userds set name='tt' where id=1";
                com.ExecuteNonQuery();
            }
    
            // 02 从声明 TransactionScope 到调用 Complete 方法之间有任何错误,Complete 方法都不会被调用。
    
            ts.Complete(); // 03 没有任何异常调用 Complete 方法
        } // 04 调用 TransactionScope.Dispose() 方法,在这个方法中判断是否执行过 Complete 方法,如果是提交事务,否回滚。
    }
    catch (Exception ex)
    {
        string dd = ex.Message;
    }




    知识改变命运,奋斗成就人生!
    • 已标记为答案 YiChun Chen 2010年1月14日 10:06
    2010年1月14日 1:31
    版主

全部回复

  • try
    {
        using (TransactionScope ts = new TransactionScope())
        {
            string conns = ConfigurationManager.AppSettings["ConnString"].ToString();

            using (SqlConnection conn = new SqlConnection(conns))
            {
                conn.Open();
                SqlCommand com = conn.CreateCommand();
                com.CommandText = "update users set name='tt' where id=2";
                com.ExecuteNonQuery();
                com.CommandText = "update userds set name='tt' where id=1";
                com.ExecuteNonQuery();
            }

            ts.Complete();
        }
    }
    catch (Exception ex)
    {
        string dd = ex.Message;
    }


    知识改变命运,奋斗成就人生!
    2010年1月13日 8:38
    版主
  • 上面这样写会更标准一些,至于为什么回滚,你可以看看错误信息。
    知识改变命运,奋斗成就人生!
    2010年1月13日 8:44
    版主
  • 你把ts.Complete();
    个人认为:写在try外面,不管成功,失败都会进行提交,导致你第一条执行成功,第二条失败,

    写在里面则不一样

    和你一样的问题:  http://social.microsoft.com/Forums/en-US/visualcshartzhchs/thread/8a5bdb9c-1bd0-48cd-9ff1-9e394ec0eb63


    努力+方法=成功
    2010年1月13日 8:53
  • msdn上不会出错吧

    2010年1月13日 9:26
  • 两个表名不一致问题 是否打错了  
      com.CommandText = "update users set name='tt' where id=2";
                com.ExecuteNonQuery();
                com.CommandText = "update userds set name='tt' where id=1";
                com.ExecuteNonQuery();
    2010年1月13日 9:53
  • 第二个表不一样,是人为写的一个错误,这样不就异常了么

    2010年1月13日 10:08
  • 你好!
         这里文档写的有些问题,我已经在你的另外一个帖子中做了回复:
    把try...catch放在using (TransactionScope scope = new TransactionScope())外面!
    或是保存原来的逻辑,但是在catch中重新抛出异常!
    周雪峰
    • 已标记为答案 YiChun Chen 2010年1月14日 10:06
    2010年1月13日 10:46
    版主
  • 好多谢,我已经明白了,可惜我买的书和网上都写错了
    2010年1月13日 14:29
  • 不客气啊!
    周雪峰
    2010年1月13日 15:27
    版主
  • 你好!

    这个示例的确是的问题的,这里我再补充说明一下 TransactionScope 运行的基本逻辑,希望能帮助你更好的理解使用它。

    try
    {
        using (TransactionScope ts = new TransactionScope()) // 01 声明实例的同时开启事务
        {
            string conns = ConfigurationManager.AppSettings["ConnString"].ToString();
    
            using (SqlConnection conn = new SqlConnection(conns))
            {
                conn.Open();
                SqlCommand com = conn.CreateCommand();
                com.CommandText = "update users set name='tt' where id=2";
                com.ExecuteNonQuery();
                com.CommandText = "update userds set name='tt' where id=1";
                com.ExecuteNonQuery();
            }
    
            // 02 从声明 TransactionScope 到调用 Complete 方法之间有任何错误,Complete 方法都不会被调用。
    
            ts.Complete(); // 03 没有任何异常调用 Complete 方法
        } // 04 调用 TransactionScope.Dispose() 方法,在这个方法中判断是否执行过 Complete 方法,如果是提交事务,否回滚。
    }
    catch (Exception ex)
    {
        string dd = ex.Message;
    }




    知识改变命运,奋斗成就人生!
    • 已标记为答案 YiChun Chen 2010年1月14日 10:06
    2010年1月14日 1:31
    版主