ho pensato su questo argomento per un po 'e si avvicinò con una soluzione molto semplice che non ho visto prima così ho voluto condividere questo:
Come è impossibile rigenerare il stesso errore, si deve lanciare un errore che è molto facile da mappare all'errore originale, ad esempio aggiungendo un numero fisso come 100000 ad ogni errore di sistema.
Dopo che i messaggi appena mappate sono aggiunti al database, è possibile gettare qualsiasi errore di sistema con un offset fisso di 100000
Ecco il codice per la creazione dei messaggi mappate (questo deve essere fatto solo una . tempo per l'intera istanza di SQL Server evitare conflitti con gli altri messaggi definiti dall'utente con l'aggiunta di un offset come 100000 in questo caso appropriata):
DECLARE messageCursor CURSOR
READ_ONLY
FOR select
message_id + 100000 as message_id, language_id, severity, is_event_logged, [text]
from
sys.messages
where
language_id = 1033
and
message_id < 50000
and
severity > 0
DECLARE
@id int,
@severity int,
@lang int,
@msgText nvarchar(1000),
@withLog bit,
@withLogString nvarchar(100)
OPEN messageCursor
FETCH NEXT FROM messageCursor INTO @id, @lang, @severity, @withLog, @msgText
WHILE (@@fetch_status <> -1)
BEGIN
IF (@@fetch_status <> -2)
BEGIN
set @withLogString = case @withLog when 0 then 'false' else 'true' end
exec sp_addmessage @id, @severity, @msgText, 'us_english', @withLogString, 'replace'
END
FETCH NEXT FROM messageCursor INTO @id, @lang, @severity, @withLog, @msgText
END
CLOSE messageCursor
DEALLOCATE messageCursor
E questo è il codice di alzare i codici di errore di nuova creazione che hanno una correzione offset rispetto al codice originale:
C'è un piccolo avvertimento: in questo caso non è possibile fornire un messaggio.Ma questo può essere aggirato aggiungendo un% s aggiuntivo nella chiamata sp_addmessage o cambiando tutti i messaggi mappati sul proprio modello e fornendo i parametri corretti nella chiamata al rialzo. La cosa migliore è impostare tutti i messaggi sullo stesso modello come '% s (riga:% d procedura:% s)% s', quindi puoi fornire il messaggio originale come primo parametro e aggiungere la vera procedura e linea e il tuo messaggio come gli altri parametri.
Nel client è ora possibile eseguire tutte le normali operazioni di gestione delle eccezioni come se fossero stati lanciati i messaggi originali, è sufficiente ricordare di aggiungere l'offset della correzione. È anche possibile gestire le eccezioni originali e rilanciati con lo stesso codice come questo:
switch(errorNumber)
{
case 8134:
case 108134:
{
}
}
Quindi non hanno nemmeno bisogno di sapere se si tratta di un rilanciati o l'errore originale, è sempre giusta, anche se si è dimenticato di gestisci i tuoi errori e l'errore originale è sfuggito.
Ci sono alcuni miglioramenti menzionati altrove riguardo l'aumento di messaggi che non è possibile aumentare o gli stati che non è possibile utilizzare. Quelli sono lasciati qui per mostrare solo il nucleo dell'idea.
Non penso che tu abbia bisogno di transazioni se vuoi solo cogliere l'errore originale: semplicemente non usare TRY/CATCH o RAISERROR() sul lato T-SQL. Inoltre, l'approccio TransactionScope funziona bene per query semplici o SP, ma ci sono casi d'angolo con SP più complessi in cui non fa la cosa giusta. – RickNZ
@RickNZ, ho dimenticato di menzionare nella domanda che sto usando due istruzioni INSERT ed è per questo che è necessaria la transazione. Buon contributo però! –