Chúng tôi có bắt buộc phải xử lý Giao dịch bằng Mã C # cũng như trong thủ tục được lưu trữ không


14

Chúng tôi có thực sự yêu cầu xử lý giao dịch trong c # cũng như xử lý lưu trữ cơ sở dữ liệu cả hai bên

C #:

Using(transaction with transaction scope)
{
     Execute stored proc;
     Transaction. Complete;
}

Thủ tục lưu trữ SQL:

Create process
As
Begin try
    Begin transaction
    Commit
End try
Begin catch
    Rollback
End catch

Câu trả lời:


20

Trước tiên , bạn phải luôn luôn xử lý giao dịch đúng cách trong tất cả các quy trình của mình để không gặp vấn đề gì nếu chúng được gọi bằng mã ứng dụng, bởi một quy trình khác, riêng lẻ trong một truy vấn đặc biệt, bởi một công việc của Tác nhân SQL hoặc một số phương tiện khác . Nhưng các câu lệnh DML đơn lẻ hoặc mã không thực hiện bất kỳ sửa đổi nào sẽ không cần Giao dịch rõ ràng. Vì vậy, những gì tôi muốn giới thiệu là:

  • Luôn có cấu trúc TRY / CATCH để các lỗi có thể được xử lý đúng
  • Tùy chọn bao gồm 3 phần xử lý giao dịch trong mã bên dưới nếu bạn có nhiều câu lệnh DML (vì bản thân một câu lệnh là một giao dịch). TUY NHIÊN, ngoài việc thêm một số mã bổ sung khi không cần thiết, nếu một người thích có một mẫu nhất quán, thì việc giữ trong 3 khối IF liên quan đến giao dịch sẽ không gây hại gì. Nhưng trong trường hợp đó, tôi vẫn khuyên bạn không nên giữ 3 khối IF liên quan đến Giao dịch cho các procs chỉ (chỉ đọc).

Khi thực hiện 2 hoặc nhiều câu lệnh DML, bạn cần sử dụng một số thứ theo các dòng sau (cũng có thể được thực hiện cho các hoạt động DML đơn lẻ nếu thích nhất quán):

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;

Khi thực hiện chỉ 1 câu lệnh DML hoặc chỉ một CHỌN, bạn có thể thoát khỏi chỉ bằng cách sau:

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;

Thứ hai , bạn nên xử lý các giao dịch tại các lớp ứng dụng duy nhất nếu bạn cần phải thực hiện hơn 1 truy vấn / thủ tục lưu trữ và tất cả họ đều cần phải được nhóm lại thành một hoạt động nguyên tử. Thực hiện một lần duy nhất SqlCommand.Execute___chỉ cần trong một lần thử / bắt chứ không phải trong Giao dịch.

Nhưng, có đau không khi thực hiện Giao dịch ở lớp ứng dụng khi chỉ thực hiện một cuộc gọi? Nếu nó yêu cầu MSDTC (Điều phối viên giao dịch phân tán của Microsoft) thì hệ thống sẽ nặng hơn một chút khi thực hiện việc này ở lớp ứng dụng khi không cần thiết. Cá nhân, tôi thích tránh các giao dịch dựa trên lớp ứng dụng trừ khi thực sự cần thiết vì nó cắt giảm tiềm năng của các giao dịch mồ côi (nếu có lỗi xảy ra với mã ứng dụng trước khi thực hiện cam kết hoặc khôi phục). Tôi cũng đã thấy rằng đôi khi việc gỡ lỗi một số tình huống khó khăn hơn một chút. Nhưng điều đó đang được nói, tôi không thấy bất cứ điều gì sai về mặt kỹ thuật cũng xử lý các giao dịch tại các lớp ứng dụng khi thực hiện một single procgọi; một lần nữa, một câu lệnh DML là giao dịch của chính nó và không cần bất kỳ xử lý giao dịch rõ ràng ở một trong hai lớp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.