5

最近、興味深い動作に気付きました。

SqlCommand.ExecuteScalar()を使用して MS SQL ストアド プロシージャを実行すると、アプリケーションはSELECTの実行後に表示される SQL エラーまたは PRINT をまったく認識していないようです。

最も可能性の高い説明は、ストアド プロシージャが終了するのを待たずに、SELECT の結果が表示された直後にフロー制御が C# に渡されることです (ただし、ストアド プロシージャはその下でサイレントに実行を続けます)。

明らかな利点はパフォーマンスの向上です (結果は既にわかっているため、待つ必要はありません)。残念ながら、C# アプリは、その時点以降に発生する可能性のある SQL 例外を認識しません。

誰かが私の説明を確認できますか? この動作を変更できますか?

4

1 に答える 1

2

ExecuteNonQuery メソッドは、"ExecuteReader" を呼び出し、返されたリーダー オブジェクトに対してすぐに "Close" を呼び出します。ExecuteScalar は「Read」を 1 回呼び出し、最初の値 (インデックス 0) を選択してから「Close」を呼び出します。

DataReader は基本的に特殊なネットワーク ストリームにすぎないため、サーバーが送信したとしても、現在の場所 (Close が呼び出されたとき) に返される情報は、実際のクライアント コンポーネントに到達することはありません。実装は、不要な場合に大量のデータを返さないようにするためのものです。

あなたの場合、この問題には 2 つの解決策があります。

  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 に答える