İlk olarak , tüm prosedürlerinizde her zaman uygun işlem yönetimine sahip olmalısınız, böylece uygulama koduyla, başka bir yordamla, ayrı bir ad hoc sorguda, bir SQL Agent işiyle veya başka bir yolla çağrılmaları önemli değildir. . Ama herhangi bir değişiklik yapmaz tek DML ifadeleri veya kod, etmez ihtiyaç açık bir İşlem. Yani, ne tavsiye ediyorum:
- Hataların düzgün bir şekilde kabarması için daima TRY / CATCH yapısına sahip olun
- İsteğe bağlı olarak, birden fazla DML ifadeniz varsa (tek bir ifade kendi başına bir işlem olduğu için) aşağıdaki koda 3 İşlem işleme parçasını ekleyin. Ancak, özellikle gerekli olmayan bazı ek kodlar eklemek dışında, tutarlı bir şablona sahip olmayı tercih ederseniz, İşlemle ilgili 3 IF bloğunda tutmak zarar vermez. Ancak bu durumda , yalnızca SELECT (yalnızca salt okunur) işlemlerde 3 İşlemle ilgili IF bloğunun tutulmamasını öneririm .
2 veya daha fazla DML ifadesi yaparken , aşağıdakilerin satırları boyunca bir şey kullanmanız gerekir (bu, tutarlı olmasını tercih ederse tek DML işlemleri için de yapılabilir):
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;
Yalnızca 1 DML ifadesi veya yalnızca bir SELECT yaparken, aşağıdakilerden kaçabilirsiniz:
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;
İkincisi , uygulama katmanındaki işlemi yalnızca 1'den fazla sorgu / saklı yordamı yürütmeniz ve hepsinin bir atomik işlem halinde gruplandırılması gerekiyorsa işlemeniz gerekir. Tek bir SqlCommand.Execute___
işlemin sadece bir deneme / yakalamada olması gerekir, ancak bir İşlemde olması gerekmez.
Ancak, yalnızca tek bir arama yaparken uygulama katmanında bir İşlem yapmak acıyor mu? MSDTC (Microsoft Dağıtılmış İşlem Düzenleyicisi) gerektiriyorsa, açıkça gerekli olmadığında uygulama katmanında bunu yapmak sistemde biraz daha ağırdır. Şahsen, artık yetim işlemler için potansiyeli azaltmadığı sürece kesinlikle uygulama katmanı tabanlı işlemlerden kaçınmayı tercih ediyorum (taahhüt veya geri alma işleminden önce uygulama kodunda bir sorun varsa). Ayrıca, bazı durumlarda hata ayıklamayı biraz daha zorlaştırdığını da buldum. Ancak söyleniyor, teknik olarak yanlış bir şey görmüyorum , aynı zamanda tek bir işlem yaparken uygulama katmanındaki işlemi de ele alıyorumaramak; Yine, tek bir DML deyimi kendi işlem ve gelmez ihtiyaç ya katmanında ele herhangi bir açık işlem.