2013-03-07 73 views
5

最近我發現了有趣的行爲。SELECT後,ExecuteScalar會立即返回嗎?

具有當MS SQL使用SqlCommand.ExecuteScalar存儲過程跑(),我的應用程序似乎是完全不知道以完成其出現SELECT之後的任何SQL錯誤或打印。

最可能的解釋是,在出現任何SELECT結果後立即向C#提供流控制,而不等待存儲過程完成(儘管存儲過程繼續在下面靜默執行)。不幸的是,C#應用程序並不知道任何可能在該點之後發生的SQL異常,因爲它的性能提高了(不需要等待,因爲結果已經知道)。

任何人都可以證實我的解釋嗎?這種行爲可以改變嗎?

+1

這可能會回答你的問題:http://stackoverflow.com/questions/7024109/how-can-i-get-an-error-message-that-happens-when- using-executenonquery,這可能也是有幫助的:http://support.microsoft.com/kb/321903/en-us – 2013-03-07 14:28:27

+0

如果您不讀取結果直到流結束,則會發生DataReaders。不知道是否適用於'ExecuteScalar'。 – 2013-03-07 15:31:04

回答

1

ExecuteNonQuery方法將調用「ExecuteReader」並立即調用返回的reader對象上的「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