Apakah kita diharuskan untuk menangani Transaksi dalam Kode C # dan juga dalam prosedur tersimpan

14

Apakah kita benar-benar memerlukan penanganan transaksi di c # juga proses penyimpanan basis data kedua belah pihak

C #:

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

Prosedur tersimpan SQL:

Create process
As
Begin try
    Begin transaction
    Commit
End try
Begin catch
    Rollback
End catch
Rakesh Gaur
sumber

Jawaban:

20

Pertama , Anda harus selalu memiliki penanganan transaksi yang tepat dalam semua prosedur Anda sehingga tidak masalah jika mereka dipanggil oleh kode aplikasi, dengan prosedur lain, secara individual dalam permintaan ad-hoc, oleh pekerjaan SQL Agent, atau cara lain . Tetapi pernyataan DML tunggal, atau kode yang tidak melakukan modifikasi, tidak memerlukan Transaksi eksplisit. Jadi, yang saya rekomendasikan adalah:

  • Selalu memiliki struktur TRY / CATCH sehingga kesalahan dapat digelembungkan dengan benar
  • Secara opsional sertakan 3 bagian penanganan Transaksi dalam kode di bawah ini jika Anda memiliki beberapa pernyataan DML (karena satu pernyataan adalah transaksi itu sendiri). NAMUN, di luar menambahkan beberapa kode tambahan di mana itu tidak diperlukan secara khusus, jika seseorang lebih memilih untuk memiliki template yang konsisten, maka tidak ada salahnya untuk tetap dalam 3 blok IF terkait transaksi. Tetapi dalam hal ini saya masih merekomendasikan untuk tidak menyimpan 3 blok IF terkait transaksi untuk proksi SELECT saja (yaitu hanya baca).

Saat melakukan 2 atau lebih pernyataan DML, Anda perlu menggunakan sesuatu di sepanjang baris berikut ini (yang juga dapat dilakukan untuk operasi DML tunggal jika orang lebih suka konsisten):

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;

Saat melakukan hanya 1 pernyataan DML atau hanya SELECT, Anda bisa lolos hanya dengan yang berikut:

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;

Kedua , Anda harus menangani transaksi di lapisan aplikasi hanya jika Anda perlu menjalankan lebih dari 1 prosedur permintaan / tersimpan dan semuanya harus dikelompokkan ke dalam operasi atom. Melakukan tunggal SqlCommand.Execute___hanya perlu di coba / tangkap, tetapi tidak dalam Transaksi.

Tapi, apakah salahnya melakukan Transaksi di lapisan aplikasi ketika hanya melakukan satu panggilan? Jika memerlukan MSDTC (Koordinator Transaksi Terdistribusi Microsoft) maka itu sedikit lebih berat pada sistem untuk melakukan ini pada lapisan aplikasi ketika tidak secara tegas diperlukan. Secara pribadi, saya lebih suka menghindari transaksi berbasis-lapisan aplikasi kecuali benar-benar diperlukan karena mengurangi potensi transaksi yatim (jika ada yang salah dengan kode aplikasi sebelum melakukan komit atau kembalikan). Saya juga menemukan bahwa kadang-kadang membuat debugging situasi tertentu sedikit lebih sulit. Tapi itu dikatakan, saya tidak melihat ada yang salah secara teknis dengan juga menangani transaksi pada lapisan aplikasi ketika membuat satu procpanggilan; sekali lagi, pernyataan DML tunggal adalah transaksi sendiri dan tidak memerlukan penanganan transaksi eksplisit di kedua lapisan.

Solomon Rutzky
sumber