2010-01-18 15 views
6

Si tratta di un follow-up alla domanda Nested stored procedures containing TRY CATCH ROLLBACK pattern?stack di chiamate di registrazione di SQL Server quando la segnalazione degli errori

Nel blocco catch io uso una stored procedure per segnalare (reraise) l'errore con la lettura da ERROR_MESSAGE(), ERROR_PROCEDURE (), ERROR_LINE(), ecc. Come descritto in here ho anche un controllo in modo che possa determinare se l'errore è già stato riscritto (questo accade con stored procedure nidificate poiché le informazioni di errore vengono trasmesse attraverso ogni blocco TRY CATCH).

Quello che vorrei fare, direttamente in "ReportError", o indirettamente con il mio pattern (come descritto nella prima domanda), è registrare una traccia di stack - quindi quando ReportError rileva che sta recuperando un errore generato da stesso, aggiunge il prossimo livello dello stack al messaggio di errore. Questo mi aiuta a evitare i casi in cui vedo un messaggio di errore proveniente da una piccola procedura memorizzata, senza alcun modo di sapere come lo chiamano. Se provo a farlo direttamente in ReportError, fallisce, dal momento che l'errore di rethrown viene segnalato come proveniente da ReportError - solo l'errore originale è visibile.

C'è qualche modo per ReportError per eseguire una traccia di stack in SQL Server, senza passare un argomento a ogni singola stored procedure e senza mantenere manualmente tale traccia con la tabella #temp? Fondamentalmente voglio una chiamata ricorsiva di ERROR_PROCEDURE() e ERROR_LINE().

+1

Ho appena aggiunto un post al mio blog che potrebbe aiutarti. Vi mostro come creare uno stack di chiamate in SQL Server. http://www.thecodepage.com/post/TIP-A-Call-Stack-in-SQL-Server.aspx –

+0

@GabrielMcAdams Il link al tuo articolo è rotto. Qualche possibilità che tu possa aggiornarlo o pubblicare la soluzione come risposta qui? –

risposta

1

Ok, io aggiungo la nostra gestione indietro nel :-)

L'ERROR_% errore Le funzioni() sono visibili nell'ambito del blocco CATCH. Questo significa che è possibile utilizzare in una chiamata proc o la funzione memorizzata in ciascun blocco CATCH

E con stored procedure nidificate, è utile sapere che cosa ha causato l'errore e quello che sta accedendo l'errore

... 
END TRY 
BEGIN CATCH 
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
     ROLLBACK TRANSACTION 
    EXEC dbo.MyExceptionHandler @@PROCID, @errmsg OUTPUT; 
    RAISERROR (@errmsg, 16, 1); 
END CATCH 

---with this handler (cut down version of ours) 
CREATE PROCEDURE dbo.MyExceptionHandler 
    @CallerProcID int, 
    @ErrorMessage varchar(2000) OUTPUT 
WITH EXECUTE AS OWNER --may be needed to get around metadata visibility issues of OBJECT_NAME 
AS 
SET NOCOUNT, XACT_ABORT ON; 

BEGIN TRY 
    SET @ErrorMessage = --cutdown 
      CASE 
       WHEN @errproc = @callerproc THEN  --Caller = error generator 
         --build up stuff 

       ELSE --Just append stuff    --Nested error stack 
      END; 

    IF @@TRANCOUNT = 0 
     INSERT dbo.Exception (Who, TheError, WhatBy, LoggedBy) 
     VALUES (ORIGINAL_LOGIN()), RTRIM(ERROR_MESSAGE()), ERROR_PROCEDURE(), OBJECT_NAME(@CallerProcID)); 
END TRY 
BEGIN CATCH 
    --and do what exactly? 
END CATCH 
GO 

Questo è il idea di base comunque: ogni blocco CATCH è semplice, il lavoro continua nel gestore degli errori. Ad esempio, aggiungi ERROR_NUMBER() se vuoi

0

Una risposta limitata a questo sarebbe passare OBJECT_NAME (@@ PROCID) alla procedura ReportError - quando ReportError rileva che sta recuperando un errore ricorsivo (un errore generato da solo), può utilizzare questo valore e aggiungerlo al messaggio di errore, fornendo una traccia dello stack parziale (stack trace non avrà numeri di riga, tranne per il primo elemento)

Problemi correlati