2013-03-07 10 views
5

Interessantes Verhalten wurde von mir vor kurzem bemerkt.Gibt ExecuteScalar sofort nach SELECT zurück?

Wenn MS SQL gespeichert-Prozedur, die lief mit SqlCommand.ExecuteScalar(), meine Anwendung scheint auf alle SQL-Fehler oder Drucke völlig ahnungslos zu sein, die erscheinen, nachdem SELECT erfolgt.

Die wahrscheinlichste Erklärung ist, dass die Ablaufsteuerung C# unmittelbar nach dem Erscheinen eines SELECT-Ergebnisses übergeben wird, ohne dass die gespeicherte Prozedur beendet werden muss (obwohl die gespeicherte Prozedur die Ausführung still unterhalb ausführt).

Offensichtlicher Vorteil ist der Leistungsgewinn (keine Wartezeiten, da das Ergebnis bereits bekannt ist), leider weiß C# app keine SQL-Ausnahmen, die nach diesem Punkt passieren könnten.

Kann jemand meine Erklärung bestätigen? Könnte dieses Verhalten geändert werden?

+1

Dies könnte Ihre Frage beantworten: http://stackoverflow.com/questions/7024109/how-can-i-get-an-error-message-that-happens-when- using-excutenonquery und das könnte auch hilfreich sein: http://support.microsoft.com/kb/321903/en-us –

+0

Dies geschieht mit DataReaders, wenn Sie nicht bis zum Ende des Streams über das Ergebnis lesen. Ich weiß nicht, ob das für "ExecuteScalar" gilt. –

Antwort

1

Die ExecuteNonQuery-Methode ruft "ExecuteReader" auf und ruft sofort "Close" für das zurückgegebene Reader-Objekt auf. ExecuteScalar ruft einmal "Read" auf, wählt den ersten Wert aus (Index 0) und ruft dann "Close" auf.

Da die Datareader mehr als ein spezialisiertes Netzwerk Strom im wesentlichen nichts ist, alle Informationen, die zurückgegeben wird afther es aktuelle Position ist (wenn Schließen genannt wird) wird einfach nie die tatsächlichen Client-Komponenten erreichen, obwohl der Server Macht geschickt haben es. Durch die Implementierung wird vermieden, dass eine große Datenmenge zurückgegeben wird, wenn keine Daten erforderlich sind.

In Ihrem Fall sehe ich zwei Lösungen für dieses Problem.

  1. stellen Sie sicher, dass Sie ExecuteReader verwenden stattdessen und den ganzen Weg durch das Ergebnis lesen:

    using(var reader = command.ExecuteReader()) 
    { 
        do 
        { 
          while (reader.Read()) { /* whatever */ }; 
        } while (reader.NextResult()); 
    } 
    
  2. Wenn Sie die Server-Seite steuern kann, wird es helfen, die eigentliche „Send- zu bewegen to-client "Wählen Sie das Ende des Verfahrens oder der betreffenden Charge aus. Wie folgt aus:

    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 
    
Verwandte Themen