5

我最近注意到了一些有趣的行为。

当使用SqlCommand.ExecuteScalar()运行 MS SQL 存储过程时,我的应用程序似乎完全不知道SELECT完成后出现的任何 SQL 错误或 PRINT。

最可能的解释是,在任何 SELECT 结果出现后立即向 C# 提供流控制,而无需等待存储过程完成(尽管存储过程在下面默默地继续执行)。

明显的优势是性能提升(无需等待,因为结果是已知的),不幸的是 C# 应用程序不知道在那之后可能发生的任何 SQL 异常。

谁能证实我的解释?这种行为可以改变吗?

4

1 回答 1

2

ExecuteNonQuery 方法将调用“ExecuteReader”并立即对返回的阅读器对象调用“Close”。ExecuteScalar 将调用一次“Read”,取出第一个值(索引 0),然后调用“Close”。

由于 DataReader 本质上只不过是一个专门的网络流,因此在其当前位置(调用 Close 时)之后返回的任何信息将永远不会到达实际的客户端组件,即使服务器可能已经发送了它。这样的实现是为了避免在不需要时返回大量数据。

在你的情况下,我看到了这个问题的两种解决方案。

  1. 确保您改用 ExecuteReader,并一直阅读结果:

    using(var reader = command.ExecuteReader())
    {
        do 
        {
              while (reader.Read()) { /* whatever */ };
        } while (reader.NextResult());
    }
    
  2. 如果您可以控制服务器端,这将有助于将实际的“发送到客户端”选择移动到有问题的过程或批处理的末尾。像这样:

    create proc Demo
    as
    declare @result int
    select top 1 @result = Id from MyTable where Name = 'testing'
    print 'selected result...'
    select @result Id  -- will send a column called "Id" with the previous value
    go
    
于 2013-03-12T23:16:30.500 回答