Ich möchte dieselbe Ausnahme in SQL Server erneut auslösen, die in meinem Try-Block aufgetreten ist. Ich kann dieselbe Nachricht senden, aber ich möchte denselben Fehler auslösen.
BEGIN TRANSACTION
BEGIN TRY
INSERT INTO Tags.tblDomain
(DomainName, SubDomainId, DomainCode, Description)
VALUES(@DomainName, @SubDomainId, @DomainCode, @Description)
COMMIT TRANSACTION
END TRY
BEGIN CATCH
declare @severity int;
declare @state int;
select @severity=error_severity(), @state=error_state();
RAISERROR(@@Error,@ErrorSeverity,@state);
ROLLBACK TRANSACTION
END CATCH
RAISERROR(@@Error, @ErrorSeverity, @state);
Diese Zeile zeigt Fehler, aber ich möchte Funktionalität so etwas. Dies löst einen Fehler mit der Fehlernummer 50000 aus, aber ich möchte, dass eine Fehlernummer ausgegeben wird, die ich übergebe @@error
.
Ich möchte diesen Fehler nicht im Frontend erfassen
dh
catch (SqlException ex)
{
if ex.number==2627
MessageBox.show("Duplicate value cannot be inserted");
}
Ich möchte diese Funktionalität. was mit Raiseerror nicht erreicht werden kann. Ich möchte keine benutzerdefinierte Fehlermeldung am Backend geben.
RAISEERROR sollte den unten genannten Fehler zurückgeben, wenn ich ErrorNo übergebe, um in catch geworfen zu werden
Msg 2627, Level 14, State 1, Procedure spOTest_DomainInsert,
Zeile 14 Verletzung der UNIQUE KEY-Einschränkung 'UK_DomainCode'. Es kann kein doppelter Schlüssel in das Objekt 'Tags.tblDomain' eingefügt werden. Die Anweisung wurde beendet.
BEARBEITEN:
Was kann der Nachteil sein, wenn der try catch-Block nicht verwendet wird, wenn eine Ausnahme im Frontend behandelt werden soll, wenn die gespeicherte Prozedur mehrere Abfragen enthält, die ausgeführt werden müssen
quelle
raiserror
, was sich davon unterscheidet, wie c # nach a beendet wirdthrow
. Also habe ich einreturn
Inside hinzugefügt,catch
weil ich diesem Verhalten entsprechen wollte.RAISERROR()
die Dokumente . Der Schweregrad ≥11 springt nur zu einemCATCH
Block, wenn er sich innerhalb einesTRY
Blocks befindet. Also Sie müssen alsoBEGIN TRY…END CATCH
Code haben, wenn SieRAISERROR()
die Flusskontrolle beeinflussen möchten .SQL 2012 führt die throw-Anweisung ein:
http://msdn.microsoft.com/en-us/library/ee677615.aspx
quelle
ROLLBACK
Zeile ist wichtig! Ohne es können Sie eine bekommenSQLException: Cannot roll back THROW
.Erneutes Werfen innerhalb des CATCH-Blocks (Code vor SQL2012, verwenden Sie die Anweisung THROW für SQL2012 und höher):
quelle
Ich denke, Ihre Entscheidungen sind:
Irgendwann wird SQL wahrscheinlich einen Reraise-Befehl einführen oder nur bestimmte Fehler abfangen. Verwenden Sie vorerst eine Problemumgehung. Es tut uns leid.
quelle
Sie können nicht: Nur die Engine kann Fehler unter 50000 auslösen. Sie können lediglich eine Ausnahme auslösen, die so aussieht ...
Siehe meine Antwort hier bitte
Der Fragesteller hier hat clientseitige Transaktionen verwendet, um das zu tun, was er wollte, was ich für ein bisschen albern halte ...
quelle
Ok, das ist eine Problemumgehung ... :-)
Wenn Sie den catch-Block notieren, wird der Fehler nicht ausgelöst, sondern die tatsächliche Fehlernummer zurückgegeben (und die Transaktion wird ebenfalls zurückgesetzt). Wenn Sie jetzt in Ihrem .NET-Code die Ausnahme abfangen und ExecuteScalar () verwenden, erhalten Sie die gewünschte tatsächliche Fehlernummer und zeigen die entsprechende Nummer an.
Hoffe das hilft,
BEARBEITEN: - Nur ein Hinweis: Wenn Sie die Anzahl der betroffenen Datensätze ermitteln und versuchen möchten, ExecuteNonQuery zu verwenden, funktioniert die oben genannte Lösung möglicherweise nicht für Sie. Ansonsten denke ich, es würde passen, was Sie brauchen. Gib mir Bescheid.
quelle
Die Möglichkeit, die Ausführung in einer gespeicherten Prozedur zu stoppen, nachdem ein Fehler aufgetreten ist, und den Fehler an das aufrufende Programm zurückzusenden, besteht darin, jeder Anweisung zu folgen, die einen Fehler mit diesem Code auslösen könnte:
Ich war selbst überrascht, als ich herausfand, dass die Ausführung in einer gespeicherten Prozedur nach einem Fehler fortgesetzt werden kann. Wenn Sie dies nicht bemerken, kann dies zu schwer auffindbaren Fehlern führen.
Diese Art der Fehlerbehandlung Parallelen (vor .Net) Visual Basic 6. Wir freuen uns auf den Befehl Throw in SQL Server 2012.
quelle
Da Sie noch nicht zu 2012 gewechselt sind, besteht eine Möglichkeit, das Sprudeln des ursprünglichen Fehlercodes zu implementieren, darin, den Textnachrichtenteil der Ausnahme zu verwenden, die Sie aus dem catch-Block (erneut) auslösen. Denken Sie daran, dass es eine Struktur enthalten kann, z. B. XML-Text, den Ihr Aufrufercode in seinem catch-Block analysieren kann.
quelle
Sie können auch eine Wrapper-gespeicherte Prozedur für diese Szenarien erstellen, wenn die SQL-Anweisung innerhalb der Transaktion ausgeführt werden soll, und den Fehler an Ihren Code weiterleiten.
quelle
Was bringt es aus gestalterischer Sicht, Ausnahmen mit ursprünglichen Fehlernummern und benutzerdefinierten Meldungen auszulösen? Bis zu einem gewissen Grad bricht es den Schnittstellenvertrag zwischen Anwendungen und der Datenbank. Wenn Sie Originalfehler abfangen und in höherem Code behandeln möchten, behandeln Sie sie nicht in der Datenbank. Wenn Sie dann eine Ausnahme abfangen, können Sie die dem Benutzer präsentierte Nachricht in eine beliebige Nachricht ändern. Ich würde es aber nicht tun, weil es Ihren Datenbankcode hmm 'nicht richtig' macht. Wie andere sagten, sollten Sie einen Satz Ihrer eigenen Fehlercodes (über 50000) definieren und diese stattdessen auslösen. Anschließend können Sie Integritätsprobleme ("Doppelte Werte sind nicht zulässig") getrennt von potenziellen geschäftlichen Problemen behandeln - "Postleitzahl ist ungültig", "Es wurden keine Zeilen gefunden, die den Kriterien entsprechen" usw.
quelle
try { code(); } catch (Exception exc) { log(exc); throw; } finally { cleanup(); }
wothrow;
nur die ursprüngliche Ausnahme mit ihrem ursprünglichen Kontext ausgelöst wird .