先看代码           string connectionString = "Data Source=localhost;Initial Catalog=test;Persist Security Info=True;User ID=sa;Password=123456";
            SqlConnection sqlConnection = new SqlConnection(connectionString);
            string strSQL = " insert into test1 values('1','a') ";
            SqlCommand command = new SqlCommand(strSQL, sqlConnection);            sqlConnection.Open();
            command.Transaction = command.Connection.BeginTransaction();            try
            {
                command.ExecuteNonQuery();
                command.Transaction.Commit();
            }
            catch
            {
                command.Transaction.Rollback();
            }
            finally
            {
                sqlConnection.Close();
            }其中SQL语句中的第二个字段插入了a,但是数据库是数字型的。造成command.ExecuteNonQuery()出错,进入catch块Rollback,这个时候我发现在catch中command.Transaction变成了null。使得我Rollback要出异常。
但是我把第二个字段改成数字以后,但是长度超过我数据库的长度,发现Transaction就不会丢,能正常Rollback。求高手解答!

解决方案 »

  1.   

    sqlConnection.Open();
      command.Transaction = command.Connection.BeginTransaction();
    把这两句也放到try 模块里面
      

  2.   

    首先LZ要知道rollback是怎么执行的
    需要记住的是,如果出现任何错误,那么后台进程就会完全自动地回滚正在进行的事务。例如,如果启动某个事务的会话失败比如网络连接可能中断,那么PMON进程会检测到所存在的问题并回滚这个事务。如果服务器重启,那么SMON进程在数据库启动阶段会检测到这个问题并启动回滚操作。发出ROLLBACK命令时,用户可以执行手动的回滚操作。无论采用何种方式启动回滚操作,它们的机制都是相同的。回滚UPDATE语句时,未被更新的列会从撤销块复制回表数据块。如果因为省略WHRER子句(例如"delete from xx;"语句)而误删除了表中的数百万条记录,那么可以回滚这些变化。在删除操作期间,服务器进程会在从表中删除记录的同时将记录复制至撤销段。随后,使用ROLLBACK命令将这些记录插回表中,这样便没有人知道您所犯过的错误。当然,此时您必须还未执行COMMIT命令。LZ你数据库是int类型 而插入的string也就是varchar 其实在执行到command.ExecuteNonQuery();
    这里的时候就出错了,与数据库连接也就断了
      

  3.   

    LZ你说的超长数据是string类型的吗?
      

  4.   

    感兴趣,可以看下源码,微软的代码都已经经过千锤百炼了,自然有他的原因。怎么能跟我们普通理解的bug相比。而且像你这种try catch的写法是很不好的,出了什么错也不暴露出来。
      

  5.   


    是这样的,我的实际程序是一个Batch,读CSV文件,插入数据库,中间如果插入失败不能出错,只能统计异常数据的条数,要继续执行后面数据的插入,最后写入日志文件正常异常条数。但是在测试的时候发现如果有数据格式的错误的时候事务就丢了,不能正常Commit。
      

  6.   

    LZ int默认位数为4  那按照你的意思 在后台插入123456就会报错 ? 
    但是事实上 int(4) 这4个字节是按照C语言的形式保存整型数据的,可以支持2^32这么大的整数
      

  7.   

    如果LZ只是想实现不报错 
    在catch里面判断
    if( command.Transaction!=null)
    {
         command.Transaction.Rollback();     
    }
    else
    {
        return;
    }
      

  8.   


    这样是可以不报错,但是我想知道原因。
    我的数据库字段是Numberic(2,0),我插入了55555进去。是会出超长的SqlException的。
      

  9.   


    呵呵,没什么啊,可以接着讨论嘛。
    插入显然不成功,但是可以正常RollBack
      

  10.   

    唉 好人做到底吧
    numberic(x,y)X是精度,Y是比例
    你刚才插入string类型的 属于类型转换错误 错误级别16
    插入numberic(x,y) 只是超出范围 错误级别15
      

  11.   

    http://msdn.microsoft.com/zh-tw/asp.net/aa326255(en-us,VS.71).aspxMSDN上面对rollback同样做了try,求解答