请教一个貌似微软BUG的问题

xibo_826 2011-09-21 09:25:18
先看代码

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。

求高手解答!
...全文
530 40 打赏 收藏 转发到动态 举报
写回复
用AI写文章
40 条回复
切换为时间正序
请发表友善的回复…
发表回复
xibo_826 2011-09-22
  • 打赏
  • 举报
回复
期待wzd24的进一步解释!
xibo_826 2011-09-22
  • 打赏
  • 举报
回复
按照29楼的做法,新申明一个Transcation就不会错,而且我在SSMS中运行返回的错误级别是16啊,仍然费解中
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 shwicho 的回复:]
引用 16 楼 visionandy 的回复:

http://msdn.microsoft.com/zh-tw/asp.net/aa326255(en-us,VS.71).aspx

MSDN上面对rollback同样做了try,求解答


不要一味的去模仿去抄襲,找點自己需要的東西 ,功能最主要
[/Quote]

不知道你是什么意思,我想问的是在MSDN的例子程序里,对rollback进行了try,是什么原因。
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 findcaiyzh 的回复:]
引用 14 楼 visionandy 的回复:

引用 12 楼 sp1234 的回复:
你的代码看起来有点累。随便写一下吧:

C# code

sqlConnection.Open();
using(var trans= sqlConnection.BeginTransaction())
{
command.Transaction= trans;
command.Exec……
[/Quote]

这个确实是,如果没有commit,也没有rollback,就直接关掉connection,数据肯定不会提交,但是我觉得为了提高程序的可读性,应该还是显示的Rollback比较好。
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 visionandy 的回复:]

http://msdn.microsoft.com/zh-tw/asp.net/aa326255(en-us,VS.71).aspx

MSDN上面对rollback同样做了try,求解答
[/Quote]

不要一味的去模仿去抄襲,找點自己需要的東西 ,功能最主要
宝_爸 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 visionandy 的回复:]

引用 12 楼 sp1234 的回复:
你的代码看起来有点累。随便写一下吧:

C# code

sqlConnection.Open();
using(var trans= sqlConnection.BeginTransaction())
{
command.Transaction= trans;
command.ExecuteNonQuery();
trans.Comm……
[/Quote]

没有commit就没有关系吧
visionandy 2011-09-21
  • 打赏
  • 举报
回复
http://msdn.microsoft.com/zh-tw/asp.net/aa326255(en-us,VS.71).aspx

MSDN上面对rollback同样做了try,求解答
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 sp1234 的回复:]
进一步地,你也应该写

C# code

using(SqlConnection sqlConnection = new SqlConnection(connectionString))
{
........
}

这样的代码,不用写什么奇怪的finally代码。
[/Quote]

谢谢指点,但是这里我想知道的关键问题是为什么事物会丢。
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 sp1234 的回复:]
你的代码看起来有点累。随便写一下吧:

C# code

sqlConnection.Open();
using(var trans= sqlConnection.BeginTransaction())
{
command.Transaction= trans;
command.ExecuteNonQuery();
trans.Commit()……
[/Quote]

如果是两个插入呢,需要一起成功或者失败。就需要rollback了
  • 打赏
  • 举报
回复
进一步地,你也应该写
using(SqlConnection sqlConnection = new SqlConnection(connectionString))
{
........
}

这样的代码,不用写什么奇怪的finally代码。
  • 打赏
  • 举报
回复
你的代码看起来有点累。随便写一下吧:
  sqlConnection.Open();
using(var trans= sqlConnection.BeginTransaction())
{
command.Transaction= trans;
command.ExecuteNonQuery();
trans.Commit();
}


这就完了,不用写什么 rollback 代码。
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 findcaiyzh 的回复:]
还是google不到东西,很奇怪没有碰到过。
下面是我分析的结果

C# code


private void button1_Click(object sender, EventArgs e)
{
string connectionString = "Data Source=pgo_swsvr\\pgo_swsvr_sca……
[/Quote]

对,我开始也在怀疑是不是framework给rollback了
但是这样也有问题啊,我如果是字段超长为什么就不会rollback呢。
宝_爸 2011-09-21
  • 打赏
  • 举报
回复
还是google不到东西,很奇怪没有碰到过。
下面是我分析的结果

private void button1_Click(object sender, EventArgs e)
{
string connectionString = "Data Source=pgo_swsvr\\pgo_swsvr_scai;Initial Catalog=pubs;Persist Security Info=True;User ID=sa;Password=sa";
SqlConnection sqlConnection = new SqlConnection(connectionString);
string strSQL = " insert into discounts values('test', NULL, NULL, NULL, 'aaa')";
SqlCommand command = new SqlCommand(strSQL, sqlConnection);

string strSQL1 = " insert into discounts values('test', NULL, NULL, NULL, 11.22)";
SqlCommand command1 = new SqlCommand(strSQL1, sqlConnection);

sqlConnection.Open();
SqlTransaction transaction = command.Connection.BeginTransaction();
command.Transaction = transaction;
command1.Transaction = transaction;

try
{
command1.ExecuteNonQuery();
//这个时候transaction是好的
//debug时能看到IsolationLevel是readcommitted, Connection是正常值
command.ExecuteNonQuery();
command.Transaction.Commit();
}
catch(Exception ex)
{
//异常是Error converting data type varchar to numeric.
//这个时候transaction已经不在正常状态下了
//debug时看到Connection是null了
//IsolationLevel是IsolationLevel = 'transaction.IsolationLevel' threw an exception of type 'System.InvalidOperationException'
//而异常信息是{System.SystemException} = {"This SqlTransaction has completed; it is no longer usable."}
//个人推断transaction已经被自动rollback了
transaction.Rollback();
//显式执行Rollback也没有异常
command.Transaction.Rollback();
}
finally
{
sqlConnection.Close();
}
}

宝_爸 2011-09-21
  • 打赏
  • 举报
回复
我也试了下,好像就是这样。继续调查。

不过如果前面有其它语句,例如插入,更新等。由于没有commit,因此也不会corrupt数据的。我试过了。
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 findcaiyzh 的回复:]
会这样吗?google不到东西。
[/Quote]

就是查不到,所以只好发帖问了
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 pittroll 的回复:]
但是我把第二个字段改成数字以后,但是长度超过我数据库的长度,发现Transaction就不会丢,能正常Rollback。
这时候的command.ExecuteNonQuery();并没有报错误,只是没有插入而已。关于事物的一般是要定义一个SqlTransaction类型的变量的.
不要随便说编译器是有bug的。
[/Quote]

所以说我也不是很确定啊
visionandy 2011-09-21
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 chenyingshu880603 的回复:]
编译器一般不会出问题吧,如果真有这种bug,微软也早发现了吧。而且,最好不要在catch中做这种操作,这样的话还不如写存储过程呢。
[/Quote]

所以我也不好确定啊,但是事实就是这样。而且我在catch中rollback有什么问题,这个例子只有一个插入,在实际中我可能有多个更新操作,如果一个失败了,肯定要Rollback的,而且我是很简单的插入,不需要写存储过程。另外我用CLR存储过程做是同样的结果。T-SQL应该不会出问题。
小珩 2011-09-21
  • 打赏
  • 举报
回复
刚监视了一下,的确是这样,不理解了,我再看下
Gemini Dean 2011-09-21
  • 打赏
  • 举报
回复
编译器一般不会出问题吧,如果真有这种bug,微软也早发现了吧。而且,最好不要在catch中做这种操作,这样的话还不如写存储过程呢。
宝_爸 2011-09-21
  • 打赏
  • 举报
回复
会这样吗?google不到东西。
加载更多回复(19)

111,119

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧