最近我注意到了一些有趣的行为。
当使用 SqlCommand.ExecuteScalar() 运行 MS SQL 存储过程时,我的应用程序似乎完全不知道在 SELECT 之后出现的任何 SQL 错误或 PRINT完成。
最可能的解释是,在出现任何 SELECT 结果后,流控制会立即交给 C#,而无需等待存储过程完成(尽管存储过程会在下面静默地继续执行)。
明显的优势是性能提升(无需等待,因为结果已知),不幸的是,C# 应用程序不知道在那之后可能发生的任何 SQL 异常。
谁能证实我的解释?可以改变这种行为吗?
最佳答案
ExecuteNonQuery 方法将调用“ExecuteReader”并立即对返回的读取器对象调用“Close”。 ExecuteScalar 将调用“Read”一次,取出第一个值(索引 0),然后调用“Close”。
由于 DataReader 本质上只不过是一个专门的网络流,因此在它的当前位置(当调用 Close 时)返回的任何信息都永远不会到达实际的客户端组件,即使服务器可能 已发送。这样的实现是为了避免在不需要时返回大量数据。
对于您的情况,我看到了解决此问题的两种方法。
确保改用 ExecuteReader,并从头到尾读取结果:
using(var reader = command.ExecuteReader()) { do { while (reader.Read()) { /* whatever */ }; } while (reader.NextResult()); }
如果您可以控制服务器端,将有助于将实际的“发送到客户端”选择移动到相关过程或批处理的末尾。像这样:
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
关于c# - ExecuteScalar 是否在 SELECT 后立即返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15273547/