답변:
먼저 , 모든 프로 시저에서 항상 적절한 트랜잭션 처리를해야 앱 코드, 다른 프로 시저, 개별 쿼리, 개별 쿼리, SQL 에이전트 작업 또는 기타 다른 방법으로 호출되는지 여부는 중요하지 않습니다. . 그러나 단일 DML 문 또는 수정하지 않는 코드 에는 명시 적 트랜잭션이 필요 하지 않습니다 . 그래서, 내가 추천하는 것은 :
둘 이상의 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 문이나 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___
을하는 것은 시도 / 캐치에만 있어야하지만 거래에는 없습니다.
그러나 한 번만 전화를 걸 때 앱 계층에서 트랜잭션을 수행하는 것이 좋지 않습니까? MSDTC (Microsoft Distributed Transaction Coordinator)가 필요한 경우 명시 적으로 필요하지 않을 때 앱 계층 에서이 작업을 수행하는 것이 시스템에서 약간 더 무겁습니다. 개인적으로, 고아 트랜잭션의 가능성을 줄임으로써 커밋 또는 롤백 전에 앱 코드에 문제가있는 경우 앱 레이어 기반 트랜잭션을 피하는 것이 좋습니다. 또한 때로는 특정 상황을 디버깅하는 것이 조금 더 어려워진다는 것을 알았습니다. 그러나 그것은 기술적으로 것이 보이지 않습니다 문제 도 하나 만들 때 응용 계층에서 트랜잭션을 처리 시저를요구; 다시 말하지만, 단일 DML 문은 자체 트랜잭션이므로 두 계층에서 명시적인 트랜잭션 처리 가 필요 하지 않습니다 .