2009-04-20 7 views
0

J'ai une procédure stockée qui ressemble à quelque chose comme:Nombre de transactions après EXECUTE erreur


CREATE PROCEDURE my_procedure 
    @val_1 INT, 
    @val_2 INT 
AS 
SET NOCOUNT ON; 
SET XACT_ABORT ON; 

BEGIN TRY 
    BEGIN TRANSACTION; 

    INSERT INTO table_1(col_1, col_2) 
    VALUES (@val_1, @val_2); 

    COMMIT TRANSACTION; 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
    ROLLBACK TRANSACTION; 

    DECLARE 
    @ERROR_SEVERITY INT, 
    @ERROR_STATE INT, 
    @ERROR_NUMBER INT, 
    @ERROR_LINE  INT, 
    @ERROR_MESSAGE NVARCHAR(4000); 

    SELECT 
    @ERROR_SEVERITY = ERROR_SEVERITY(), 
    @ERROR_STATE = ERROR_STATE(), 
    @ERROR_NUMBER = ERROR_NUMBER(), 
    @ERROR_LINE  = ERROR_LINE(), 
    @ERROR_MESSAGE = ERROR_MESSAGE(); 

    RAISERROR('Msg %d, 
    Line %d, 
    :%s', 
    @ERROR_SEVERITY, 
    @ERROR_STATE, 
    @ERROR_NUMBER, 
    @ERROR_LINE, 
    @ERROR_MESSAGE); 
END CATCH 

Lorsque ce code est exécuté par la base de données, tout fonctionne correctement. Quand exécuter par ADO.NET je rentrerai le message d'erreur suivant:

« L'instruction INSERT en conflit avec la contrainte FOREIGN KEY » FK_table1_table2 ». Le conflit a eu lieu dans la base de données « my_database », table « dbo.table_1 », colonne « col_1 » . nombre de transactions après EXECUTE indique qu'une instruction COMMIT ou ROLLBACK tRANSACTION est manquante. nombre précédent = 1, nombre actuel = 0 "

est-ce qui se passe car le paramètre XACT_ABORT oblige une transaction de ADO.NET à être annulées ? Quel est le meilleur moyen d'éviter cette erreur?

Répondre

2

vous pouvez vérifier XACT_STATE() dans votre code puis valider ou d'annuler, vérifier ici: Use XACT_STATE() To Check For Doomed Transactions

essentiellement quelque chose comme ça va exploser

BEGIN TRANSACTION TranA 
    BEGIN TRY 
    DECLARE @cond INT; 
    SET @cond = 'A'; 
    END TRY 
    BEGIN CATCH 
    PRINT 'a' 
    END CATCH; 
    COMMIT TRAN TranA 

et quand vous vérifiez xact_state vous pouvez le contrôler

BEGIN TRANSACTION TranA 
    BEGIN TRY 
    DECLARE @cond INT; 
    SET @cond = 'A'; 
    END TRY 
    BEGIN CATCH 
    PRINT ERROR_MESSAGE(); 
    END CATCH; 
    IF XACT_STATE() =0 
    BEGIN 
    COMMIT TRAN TranA 
    END 
    ELSE 
    BEGIN 
    ROLLBACK TRAN TranA 
    END 

Jetez aussi un coup d'œil à ces deux doivent lire des liens Implementing Error Handling with Stored Procedures et Error Handling in SQL Server – a Background.

+0

Donc une meilleure approche pourrait être de ne pas utiliser XACT_ABORT dans les sprocs si je fais la gestion des erreurs TRY/CATCH? –

+0

XACT_ABORT est toujours bon à utiliser car il va effacer toute ordure restante et est également nécessaire lorsque vous faites une transaction distribuée, je vais ajouter 2 liens à ma réponse pour vous de lire – SQLMenace

2

IF XACT_STATE() = 0 BEGIN COMMIT TRAN Traña END

va générer erro. XACT_STATE() = 0 signifie qu'il n'y a pas de transaction pour valider ou annuler

XACT_STATE() = 1 signifie qu'il n'y a transaction commitable

XACT_STATE() = -1 signifie qu'il n'y a transaction uncommitable qui sera rollbacked par le moteur de base de données à la fin du contexte actuel.