回答:
まず、すべてのプロシージャで常に適切なトランザクション処理を行う必要があります。これにより、アプリケーションコード、別のプロシージャ、個別のアドホッククエリ、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を1つだけ実行すると、次のようになります。
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ステートメントはそれ自体のトランザクションであり、どちらの層でも明示的なトランザクション処理を必要としません。