先看代码
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 string connectionString = "Data Source=localhost;Initial Catalog=test;Persist Security Info=True;User ID=sa;Password=123456";
2 SqlConnection sqlConnection = new SqlConnection(connectionString);
3 string strSQL = " insert into test1 values('1','a') ";
4 SqlCommand command = new SqlCommand(strSQL, sqlConnection);
5
6 sqlConnection.Open();
7 command.Transaction = command.Connection.BeginTransaction();
8
9 try
10 {
11 command.ExecuteNonQuery();
12 command.Transaction.Commit();
13 }
14 catch
15 {
16 if(command.Transaction!=null)
17 command.Transaction.Rollback();
18 }
19 finally
20 {
21 sqlConnection.Close();
22 }
两个sql语句的错误不一样,一个是state1,一个是state2,在Ado.net中TdsParser的Run方法对不同的sql错误会有不同的处理。然后抛出不同的SqlException。
第一种情况,
insert into test1 values('1','a'),Ado.net会自动在出错后把command.Transaction赋值为null,因为这个语句无法形成一个事务,可以做一个实验,即使执行如下的sql:
begin transaction
insert into test1 values('1', 2)
insert into test1 values('1','a')
commit transaction
数据库中也不会新增任何一条记录。
所以Rollback也就没有意义了。
第二种情况可以自己做一下实验,如果不Rollback,
begin transaction
insert into test1 values('1', 2)
insert into test1 values('1',111111111111)
commit transaction
commit后记录是会写入数据库里的。
按照你的方案做了实验,发现确实如你所说。
但是我有一点不明白,在执行ExecuteNonQuery的时候,为什么超长数据的插入不会报错,commit后也不会插入数据库。
而类型转化出错的话直接Transacation就关闭了。
不好意思,刚才测试代码写错了,插入超长字段是会Catch到的。
谢谢你的回复。
using (SqlTransaction tran = con.BeginTransaction() )
{ ... tran.Commit();
}
使用以上的msdn中建议的写法
是不是差个 catch (Exception e)