none
通过ADO.NET往表中插入数据,程序到了超时时间抛出异常,但却插入成功,这个正常吗? RRS feed

  • 问题

  • 大家好。

    如题,我执行的SQL是:

    INSERT INTO Orders( ... ) OUTPUT Inserted.OrderID VALUES( ... )

    在程序中执行这条SQL语句,因到达超时时间,sqlCommand.ExecuteScalar()抛出了异常,信息为:

    System.Transactions.TransactionInDoubtException: The transaction is in doubt. ---> System.Data.SqlClient.SqlException: Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

    还有的异常信息为:

    System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.

    不管是哪种异常,都存在订单入库的情况,这让我很头疼,也给我们造成了很大的麻烦T_T,因为我一直就是在抛出异常后按照入库失败处理的,所以想问下这种情况是正常的吗?TransactionInDoubtException是如何产生的?怎么样来避免此种情况或者出现该异常以后如何判定事务是否为执行成功的?

    多谢!

    2013年3月26日 2:16

答案

  • insert 和 output是原子操作,insert成功后,output才输出数据。就是说,timeout是在insert, output之后发生的,所以已经入库。你应该使用显式事务来避免这种情况。

    想不想时已是想,不如不想都不想。

    • 已标记为答案 se_zyt 2013年3月28日 9:23
    2013年3月26日 10:12
    版主
  • 估计你是在 SqlCommand 中执行了多个语句吧, 比如你的 CommandText 中有两个语句, 第一个是 insert output, 后面还有一个什么操作

    这个如果没有使用事务的话, 当你的第2个语句执行超时的话, 第一个语句的操作是不会被回滚的

    测试了一下, 如果是 insert output 这一句超时的话, 这一句的操作是回滚的, 这个跟 output 输出的结果返回到客户端的时间看起来是没有什么关系的, 我试了一下, 一个 insert output 的操作, 直接在服务器上执行1秒, 通过慢速客户端去执行, 要30秒, 测试发现, 不管是用 ExecuteNonQuery , 还是用 ExecuteReader, 或者是用 ExecuteScalar, 效率都差不多, 都可以模拟出 Timeout 的情况, 这三种方法在 Timeout 后, insert 操作都回滚了

    • 已标记为答案 se_zyt 2013年3月28日 9:23
    2013年3月28日 6:47

全部回复

  • Did you see blocking on sql server? Any connection error in ring buffer? Is the db mirrored?
    2013年3月26日 2:42
  • insert 和 output是原子操作,insert成功后,output才输出数据。就是说,timeout是在insert, output之后发生的,所以已经入库。你应该使用显式事务来避免这种情况。

    想不想时已是想,不如不想都不想。

    • 已标记为答案 se_zyt 2013年3月28日 9:23
    2013年3月26日 10:12
    版主
  • 估计你是在 SqlCommand 中执行了多个语句吧, 比如你的 CommandText 中有两个语句, 第一个是 insert output, 后面还有一个什么操作

    这个如果没有使用事务的话, 当你的第2个语句执行超时的话, 第一个语句的操作是不会被回滚的

    测试了一下, 如果是 insert output 这一句超时的话, 这一句的操作是回滚的, 这个跟 output 输出的结果返回到客户端的时间看起来是没有什么关系的, 我试了一下, 一个 insert output 的操作, 直接在服务器上执行1秒, 通过慢速客户端去执行, 要30秒, 测试发现, 不管是用 ExecuteNonQuery , 还是用 ExecuteReader, 或者是用 ExecuteScalar, 效率都差不多, 都可以模拟出 Timeout 的情况, 这三种方法在 Timeout 后, insert 操作都回滚了

    • 已标记为答案 se_zyt 2013年3月28日 9:23
    2013年3月28日 6:47