Sql-Server
我們是否需要在 C# 程式碼和儲存過程中處理事務
我們真的需要c#中的事務處理以及數據庫儲存過程雙方嗎
C#:
Using(transaction with transaction scope) { Execute stored proc; Transaction. Complete; }
SQL儲存過程:
Create process As Begin try Begin transaction Commit End try Begin catch Rollback End catch
首先,您應該始終在所有過程中進行適當的事務處理,以便它們是否被應用程式碼、另一個過程、在臨時查詢中單獨呼叫、通過 SQL 代理作業或其他方式呼叫都無關緊要. 但是單個 DML 語句或不進行任何修改的程式碼不需要顯式事務。所以,我推薦的是:
- 始終具有 TRY / CATCH 結構,以便可以正確冒泡錯誤
- 如果您有多個 DML 語句(因為單個語句本身就是一個事務),則可以選擇在下面的程式碼中包含 3 個事務處理部分。然而,除了在不需要的地方添加一些額外的程式碼之外,如果一個人更喜歡有一個一致的模板,那麼保留在 3 個與事務相關的 IF 塊中並沒有什麼壞處。但在那種情況下,我仍然建議不要為 SELECT-only(即只讀)過程保留 3 個與事務相關的 IF 塊。
在執行 2 個或更多 DML 語句時,您需要使用以下內容(如果希望保持一致,也可以對單個 DML 操作執行此操作):
CREATE PROCEDURE [SchemaName].[ProcedureName] ( @Param DataType ... ) AS SET NOCOUNT ON; DECLARE @InNestedTransaction BIT; BEGIN TRY IF (@@TRANCOUNT = 0) BEGIN SET @InNestedTransaction = 0; BEGIN TRAN; -- only start a transaction if not already in one END; ELSE BEGIN SET @InNestedTransaction = 1; END; -- { 2 or more DML statements (i.e. INSERT / UPDATE / DELETE) } IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0) BEGIN COMMIT; END; END TRY BEGIN CATCH IF (@@TRANCOUNT > 0 AND @InNestedTransaction = 0) BEGIN ROLLBACK; END; DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(), @ErrorState INT = ERROR_STATE(), @ErrorSeverity INT = ERROR_SEVERITY(); -- optionally concatenate ERROR_NUMBER() and/or ERROR_LINE() into @ErrorMessage RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState); RETURN; END CATCH;
僅執行 1 個 DML 語句或僅執行 SELECT 時,您只需執行以下操作即可:
CREATE PROCEDURE [SchemaName].[ProcedureName] ( @Param DataType ... ) AS SET NOCOUNT ON; BEGIN TRY -- { 0 or 1 DML statements (i.e. INSERT / UPDATE / DELETE) } END TRY BEGIN CATCH DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE(), @ErrorState INT = ERROR_STATE(), @ErrorSeverity INT = ERROR_SEVERITY(); -- optionally concatenate ERROR_NUMBER() and/or ERROR_LINE() into @ErrorMessage RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState); RETURN; END CATCH;
**其次,**只有當您需要執行多個查詢/儲存過程並且它們都需要分組為原子操作時,您才應該在應用層處理事務。做單
SqlCommand.Execute___
只需要在try/catch中,而不是在Transaction中。但是,只進行一次呼叫時,在應用層進行事務是否會受到傷害?如果它需要 MSDTC(Microsoft Distributed Transaction Coordinator),那麼在沒有明確需要時在應用層執行此操作對系統來說有點重。就個人而言,除非絕對必要,否則我更喜歡避免基於應用程序層的事務,因為它減少了孤立事務的可能性(如果在執行送出或回滾之前應用程式碼出現問題)。我還發現它有時會使調試某些情況變得更加困難。但話雖如此,我認為在製作單個proc時在應用層處理事務在技術上沒有任何問題稱呼; 同樣,單個 DML 語句是它自己的事務,不需要在任一層進行任何顯式事務處理。