SQL Server: Wiederholt die Ausnahme mit der ursprünglichen Ausnahmebedingungsnummer

7

Ich verwende einen TRY CATCH-Block in einer gespeicherten Prozedur, wo ich zwei INSERT-Anweisungen habe.

Wenn etwas schief geht, kümmert sich der CATCH-Block darum, alle vorgenommenen Änderungen rückgängig zu machen, und es funktioniert gut, bis auf eine Sache!

Die Ausnahme, die von meiner ASP.NET-Anwendung abgefangen wird, ist eine SqlException mit der Nummer 50000. Dies ist nicht die ursprüngliche Zahl! (die Zahl, die ich erwartete, war eine 2627)

In der Message-Eigenschaft der Ausnahme kann ich die ursprüngliche Ausnahme-Nummer und Nachricht formatiert sehen.

Wie kann ich die ursprüngliche Ausnahmerummer erhalten?

%Vor%

Momentan wird der Rückgabewert bereits verwendet. Ich denke, dass ich einen Ausgabeparameter verwenden könnte, um die Ausnahmebedingungsnummer zu bekommen, aber ist das eine gute Idee?

Was kann ich tun, um die Ausnahmenummer zu erhalten? Danke

PS: Dies wird benötigt, weil ich zwei INSERT-Anweisungen habe.

    
Fabio Milheiro 10.12.2009, 17:54
quelle

7 Antworten

0

Danke Leute für eure Antworten. Den Fehler aus der Nachricht des neu geworfenen Exceltons zu bekommen, war etwas, was ich bereits getan hatte.

@gbn Ich mochte auch die Antwort von gbn, aber ich bleibe bei dieser Antwort, da es die ist, die am besten funktioniert, und ich poste sie hier, in der Hoffnung, dass sie auch für andere nützlich sein wird.

Die Antwort verwendet Transaktionen in der Anwendung. Wenn ich die Ausnahme in der gespeicherten Prozedur nicht abfange, erhalte ich die ursprüngliche Zahl im SqlException-Objekt. Nachdem ich die ursprüngliche Ausnahme in der Anwendung abgefangen habe, schreibe ich den folgenden Code

%Vor%

Sonst:

%Vor%

Es ist viel einfacher als ich zuerst erwartet habe!

Ссылка

    
Fabio Milheiro 11.12.2009, 12:00
quelle
11

Sie können es vielleicht so wiederholen:

%Vor%

Sie verlieren jedoch wahrscheinlich einen Bedeutungsverlust aufgrund der Platzhalter% s usw. in den Zeilen sys.messages für ERROR_NUMBER ()

Sie könnten so etwas tun, um die Nummer einzufügen und die ursprüngliche Nachricht erneut zu erhalten.

%Vor%

Die ersten 5 Zeichen sind die ursprüngliche Nummer.

Aber wenn Sie geschachtelten Code haben, dann werden Sie mit "00123 00456 Fehlertext" enden.

Ich persönlich beschäftige mich nur mit SQL-Ausnahmenummern, um meine Fehler (50000) von Suchmaschinenfehlern (z. B. fehlende Parameter) zu trennen, in denen mein Code nicht ausgeführt wird.

Schließlich können Sie den Rückgabewert übergeben.

Ich habe eine Frage dazu gestellt: SQL Server-Fehlerbehandlung: Ausnahmen und der Datenbank-Client-Vertrag

    
gbn 10.12.2009 18:47
quelle
8

Wenn Sie BEGIN TRY / BEGIN CATCH in T-SQL verwenden, verlieren Sie die ursprüngliche Exception der Engine. Sie sollten Systemfehler nicht manuell auslösen, so dass Sie die ursprüngliche Fehlernummer 2627 nicht erneut auslösen können. Die T-SQL-Fehlerbehandlung ähnelt C # / C ++ - Fehlerbehandlung nicht, es gibt keine Möglichkeit, das Original erneut zu werfen Ausnahme. Es gibt eine Reihe von Gründen, warum diese Einschränkung existiert, aber es genügt zu sagen, dass dies möglich ist und Sie können sie nicht ignorieren.

Es gibt jedoch keine Einschränkungen für die Erhöhung eigener Fehlercodes, solange sie über dem 50000-Bereich liegen. Sie registrieren Ihre eigenen Nachrichten mit sp_addmessage , wenn die Anwendung installiert ist:

%Vor%

und in Ihrem T-SQL würden Sie den neuen Fehler auslösen:

%Vor%

Im C # -Code würden Sie nach der Fehlernummer 50001 statt nach 2627 suchen:

%Vor%

Ich wünschte, es gäbe eine einfachere Antwort, aber leider ist es so wie es ist. Die T-SQL-Ausnahmebehandlung ist nicht nahtlos in die CLR-Ausnahmebehandlung integriert.

    
Remus Rusanu 10.12.2009 21:22
quelle
1

Hier ist der Code, den ich verwende, um dieses Problem zu beheben (von CATCH aus aufgerufen). Er bettet die ursprüngliche Fehlernummer in den Nachrichtentext ein:

%Vor%

Dann können Sie zum Beispiel nach SqlException.Message.Contains("2627:") suchen.

    
RickNZ 11.12.2009 11:17
quelle
1

Ich habe eine Weile über dieses Thema nachgedacht und eine sehr einfache Lösung gefunden, die ich vorher nicht gesehen habe, also wollte ich folgendes teilen:

Da es nicht möglich ist, den gleichen Fehler erneut auszulösen, muss man einen Fehler werfen, der sehr einfach dem ursprünglichen Fehler zugeordnet werden kann, indem zum Beispiel eine feste Zahl wie 100000 zu jedem Systemfehler hinzugefügt wird.

Nachdem die neu zugeordneten Nachrichten der Datenbank hinzugefügt wurden, ist es möglich, Systemfehler mit einem festen Offset von 100000 auszulösen.

Hier ist der Code zum Erstellen der zugeordneten Nachrichten (dies muss nur einmal für die gesamte SQL Server-Instanz durchgeführt werden. Vermeiden Sie Konflikte mit anderen benutzerdefinierten Nachrichten, indem Sie in diesem Fall einen entsprechenden Offset wie 100000 hinzufügen):

%Vor%

Und das ist der Code, um die neu erstellten Fehlercodes zu erzeugen, die einen festen Offset vom ursprünglichen Code haben:

%Vor%

Es gibt eine kleine Einschränkung: Sie können in diesem Fall keine Nachricht selbst eingeben. Dies kann jedoch umgangen werden, indem im sp_addmessage-Aufruf ein zusätzliches% s hinzugefügt wird oder alle zugeordneten Nachrichten in Ihr eigenes Muster geändert werden und die richtigen Parameter im raisefror-Aufruf bereitgestellt werden. Am besten ist es, alle Nachrichten auf das gleiche Muster wie '% s (Zeile:% d Prozedur:% s)% s' zu setzen, sodass Sie die ursprüngliche Nachricht als ersten Parameter angeben und die echte Prozedur und Zeile und Ihre eigene anhängen können Nachricht als die anderen Parameter.

Im Client können Sie nun alle normalen Exceptions bearbeiten, so wie die ursprünglichen Nachrichten ausgelöst wurden. Sie müssen nur daran denken, den Fix-Offset hinzuzufügen. Sie können sogar originale und erneut auftretende Ausnahmen mit dem gleichen Code behandeln:

%Vor%

Damit Sie nicht einmal wissen müssen, ob es sich um einen erneuten Fehler oder den ursprünglichen Fehler handelt, ist es immer richtig, auch wenn Sie vergessen haben, mit Ihren Fehlern umzugehen, und der ursprüngliche Fehler durchging.

Es gibt einige Verbesserungen, die an anderer Stelle erwähnt werden, wenn Sie Nachrichten aufrufen, die Sie nicht abrufen können oder die Sie nicht verwenden können. Diese sind hier weggelassen, um nur den Kern der Idee zu zeigen.

    
Uwe Wittig 29.10.2010 20:18
quelle
1

Als SQL Server & lt; 2010 ist nicht in der Lage, erneut zu werfen, der richtige Weg, dies zu tun, ist eine Transaktion zu verwenden und explizit nach dem Fehlerstatus zu suchen (denke mehr 'C' als 'C ++ / C #').

z. Körper von SP würde ungefähr so ​​aussehen:

%Vor%

Dies ist eine Lösung, die in einer gehosteten Umgebung funktioniert (in der Sie wahrscheinlich keine eigenen Fehlermeldungen erstellen können).

Diese Vorgehensweise ist zwar nicht so praktisch wie die Verwendung von Ausnahmen, behält jedoch die Systemfehlercodes bei. Es hat auch den Vorteil, mehrere Fehler pro Ausführung zurückgeben zu können.

Wenn Sie nur den ersten Fehler bombardieren wollen, fügen Sie entweder return statements ein oder wenn Sie sich mutig fühlen, ein GOTO ein Fehlerblock (denken Sie daran: Go to Statement als schädlich angesehen ), zB:

(Elemente aus der ASP.NET-Kontoverwaltung übernommen)

%Vor%     
The Real Edward Cullen 28.07.2013 15:58
quelle
0

Ich benutze das folgende Muster:

%Vor%     
Charles Bretana 10.12.2009 18:02
quelle