2016-09-26 67 views
1

我完全理解,爲了提供信息而向調用程序拋出一個錯誤是一件奇怪的事情,但是使用了我在這裏給出的,但是我從C#調用了下面的代碼。SQL Server拋出和事務

錯誤被拋出,但數據未被刪除。如果我不扔那麼數據被刪除。鑑於我在交易中有刪除,爲什麼拋出後刪除將被回滾,這是它看起來正在做的事情。

IF (@action = 'D') 
     BEGIN 
      BEGIN TRANSACTION 
       DELETE FROM dbo.inv_detail WHERE inv_id = @inv_id; 
       DELETE FROM dbo.inv_header WHERE inv_id = @inv_id; 
      COMMIT TRAN 

      --Returns an info message to indicate that the repository invoice has been deleted 
      SET @InfoMessage = 'Number: ' + LTRIM(STR(@inv_ref_nbr)) + ' for Site: ' + LTRIM(STR(@site)) + ' has been deleted'; 
      THROW 50001, @InfoMessage, 1; 
     END 

這是包裝一個try/catch內,其中美中不足的是:

BEGIN CATCH 

     SELECT @ErrorNumber = ERROR_NUMBER(), 
       @ErrorMessage = ERROR_MESSAGE(), 
       @ErrorSeverity = ERROR_SEVERITY(), 
       @ErrorState = ERROR_STATE(); 

     -- Use RAISERROR inside the CATCH block to return error 
     -- information about the original error that caused 
     -- execution to jump to the CATCH block. 
     RAISERROR (@ErrorMessage, -- Message text. 
        @ErrorSeverity, -- Severity. 
        @ErrorState  -- State. 
        ); 
    END CATCH 
+0

'如果我不扔那麼數據被刪除.'這不會意味着沒有錯誤? – TheGameiswar

+0

是的,他們正在使用它來獲取刪除回調用程序的詳細信息。他們並沒有將它用於真正的錯誤。我所做的正確的事情很可能是一個外部參數,但只是好奇拋出上面的刪除事務,儘管它已被提交。 – user441521

+0

你總是拋出錯誤'THROW 50001,@InfoMessage,1;' – TheGameiswar

回答

1

從評論推斷,這個問題造成的,因爲調用C#代碼執行事務中的T-SQL 。當發生錯誤時,C#代碼會自動檢測到它並回滾整個事務。

您提到此代碼的原始版本使用RAISERROR來引發低嚴重性錯誤。 嚴重性爲< = 10的錯誤被視爲僅用於信息,並且被SQL Server TRY...CATCH忽略 - 並且通過推斷,您正在使用的C#數據庫驅動程序會尊重這一點。

相比之下,THROW總是會產生一個嚴重性爲16的錯誤 - 將其視爲實際錯誤,被TRY...CATCH捕獲,並重新排列爲觸發回滾的C#。

(錯誤和PRINT郵件傳遞到一個SQL客戶端上從結果集不同的TDS流。一種方式來閱讀他們看到here。我的猜測是,這是原來的程序員如何閱讀返回低嚴重性消息。)