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ステートメント、または変更を行わないコードは、明示的なトランザクションを必要としません。だから、私がお勧めするのは:
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;
DMLステートメントを1つだけ、または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;
2番目、1つ以上のクエリ/ストアドプロシージャを実行する必要がある場合は、アプリレイヤーでトランザクションを処理する必要がありますonlyそれらはすべて、アトミック操作にグループ化する必要があります。単一のSqlCommand.Execute___
は、try/catchにのみ必要ですが、トランザクションには必要ありません。
しかし、1回の呼び出しのみを行うときにアプリレイヤーでトランザクションを実行することは難しいですか? MSDTC(Microsoft Distributed Transaction Coordinator)が必要な場合は、明示的に必要とされていない場合にアプリレイヤーでこれを行うと、システムで少し重くなります。個人的には、孤立したトランザクション(コミットまたはロールバックを実行する前にアプリのコードで問題が発生した場合)の可能性を減らすため、絶対に必要な場合を除いて、アプリレイヤーベースのトランザクションは避けることをお勧めします。また、特定の状況のデバッグが少し難しくなることもあります。しかし、そうは言っても、技術的には何も表示されませんalso単一のproc呼び出しを行うときに、アプリ層でトランザクションを処理します。この場合も、単一のDMLステートメントは独自のトランザクションであり、どちらのレイヤーでも明示的なトランザクション処理を必要としません。