Heute muss eine Abfrage eine Ergebnismenge über ExcuteReader zurückgeben und möchte gleichzeitig Parameter ausgeben. Zu Beginn konnte ich den Wert der Ausgabeparameter nicht ermitteln, da ich dachte, dass die gespeicherte Prozedur einen Fehler hatte. Der Test im Abfrageanalysator war korrekt und die Ausgabeparameter wurden tatsächlich geändert.
Was noch rätselhafter ist, ist, dass nach dem Auslösen einer Ausnahme während der erzwungenen Typkonvertierung die Ausgabe tatsächlich erneut erfolgen kann. Ist es unmöglich, sich eine solche Seite vorzustellen? Häufig verwendete API wird angezeigt. Ist das falsch? Mein Code ähnelt dem folgenden Szenario:
try {
using (SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)) {
int val = (int)cmd.Parameters[1].Value; // Jetzt noch leer
// mehr
}
}
Catch(Exception exp) {
throw new ApplicationException("Ausgabeparameterwert: " + cmd.Parameters[1].Value, exp); // Jetzt kann der Ausgabewert abgerufen werden
}
Es ist wirklich frustrierend. Nach einer Stunde Debuggen und Nachverfolgen
habe ich endlich die Antwort in MSDN gefunden:
Wenn Sie ein Command-Objekt mit einer gespeicherten Prozedur verwenden, können Sie die CommandType-Eigenschaft des Command-Objekts auf StoredProcedure festlegen. Wenn der CommandType StoredProcedure ist, können Sie die Parameters-Eigenschaft des Befehls verwenden, um auf Eingabe- und Ausgabeparameter und Rückgabewerte zuzugreifen. Unabhängig davon, welche Execute-Methode aufgerufen wird, kann auf die Parameters-Eigenschaft zugegriffen werden. Wenn jedoch ExecuteReader aufgerufen wird, sind der Rückgabewert und die Ausgabeparameter erst zugänglich, wenn der DataReader geschlossen wird.
Ref: http://msdn2.microsoft.com/zh-CN/library/tyy0sz6b.aspx
Das ist es, als ob ich wieder von MS getäuscht wurde. Warum bin ich unerfahren im Lernen? Ich habe das Dokument bereits geändert und
darauf zurückgegriffen. Ihre eigene Codeumgebung kann noch erläutert werden.
Denn wenn die Ausnahme abgefangen wird, wurde der Verwendungsbereich herausgesprungen, der DataReader wurde automatisch geschlossen und der Wert des Ausgabeparameters kann natürlich abgerufen werden.
Wenn Sie den Try-Catch in „using“ einfügen, können Sie ihn natürlich immer noch nicht abrufen, da er sich immer noch im „using“-Bereich befindet und der DataReader nicht geschlossen wurde.
Darüber hinaus gibt MSDN an, dass darauf nur zugegriffen werden kann, wenn der DataReader geschlossen ist, was jedoch nicht der Fall ist.
Nach dem Test kann man es wie folgt zusammenfassen:
1. Für ExecuteReader werden Ausgabeparameter und Rückgabewert als Ergebnismenge an DataReader zurückgegeben, und die Ergebnismenge ist immer die letzte.
2. Gemäß 1 müssen Sie, wenn eine Ergebnismenge vorhanden ist, um auf die Ausgabeparameter und Rückgabewerte zuzugreifen, NextResult an der Position der Ergebnismenge aufrufen, die den Ausgabeparametern und Rückgabewerten entspricht.
3. Gemäß 1 kann, wenn Execute keine Ergebnismenge zurückgibt, direkt darauf zugegriffen werden (beachten Sie, dass kein Aufruf von Read() erforderlich ist).
4. Achten Sie besonders auf die Notwendigkeit, NextResult mehrmals aufzurufen, wenn mehrere Ergebnismengen zurückgegeben werden. Wenn die Anzahl der Ergebnismengen dynamisch ist, ist der Rückgabewert von nextResult() falsch.
5. Selbst wenn die Option CommandBehavior.SingleResult für ExecuteReader angegeben ist (die eine einzelne Ergebnismenge zurückgibt, also die erste Ergebnismenge des Stapels), werden die Ausgabeparameter als Ergebnismenge zurückgegeben.
6. Beim Schließen des DataReaders (Close()) werden die Ausgabeparameter gefüllt und sind somit zugänglich.
7. Da der DataReader nur vorwärts lesend ist, kann auf die vorherige Ergebnismenge nicht mehr zugegriffen werden, selbst wenn die Ausgabeparameter über die NextResult-Methode vor dem Schließen des DataReader abgerufen werden (in einigen Fällen möchten Sie die Ergebnismenge möglicherweise dynamisch über die Ausgabe steuern). Parameter. Besuch).
8. Um das Problem in 6 zu lösen, können Sie den Ausgabeparameter nicht direkt als erstes Ergebnis zurückgeben (SELECT @parmname).
Ich hoffe, dass es keine Diskrepanz gibt hilfreich für Anfänger.
Ref:
http://www.bigcircleboy.net/583a194f-2c2c-4662-9036-4e2f0eb262396084313157728108.html