Чи потрібно нам обробляти транзакції в коді C #, а також у збереженій процедурі


14

Чи дійсно нам потрібна обробка транзакцій в c #, а також процес зберігання бази даних з обох сторін

C #:

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

Збережена процедура SQL:

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

Відповіді:


20

По-перше , ви завжди повинні мати належну обробку транзакцій у всіх своїх процедурах, так що не має значення, чи викликаються вони кодом програми, іншою процедурою, індивідуально за спеціальним запитом, завданням агента SQL чи іншим способом . Але окремим операторам DML або коду, який не вносить жодних змін, не потрібна явна транзакція. Отже, що я рекомендую:

  • Завжди має структуру TRY / CATCH, щоб помилки могли бути належним чином розкриті
  • Необов’язково включайте 3 фрагменти обробки транзакцій у наведений нижче код, якщо у вас є кілька операторів DML (оскільки один оператор сам по собі є транзакцією). ЗАРАЗ, за винятком додавання додаткового коду там, де він конкретно не потрібен, якщо хтось вважає за краще мати послідовний шаблон, то це не завадить триматись у 3 блоках IF, пов'язаних з транзакціями. Але в цьому випадку я все-таки рекомендую не зберігати 3 IF-пов'язані з транзакцією блоки IF для проектів SELECT (тобто лише для читання).

Виконуючи 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;

Виконуючи лише 1 оператор 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;

По-друге , вам слід обробляти транзакції на рівні додатків, лише якщо вам потрібно виконати більше 1 запиту / збереженої процедури, і всі вони повинні бути згруповані в атомну операцію. Робити сингл SqlCommand.Execute___потрібно лише в спробі / лові, але не в транзакції.

Але чи не боляче робити транзакцію на рівні програми, коли здійснюєте лише один дзвінок? Якщо для цього потрібен MSDTC (координатор розподілених транзакцій Microsoft), то в системі дещо важче це робити на рівні додатків, коли це прямо не потрібно. Особисто я вважаю за краще уникати трансакцій на основі додатків, якщо це абсолютно не потрібно, оскільки це зменшує потенціал для осиротілих транзакцій (якщо щось пішло не так з кодом програми перед тим, як здійснити комісію або відкат). Я також виявив, що іноді налагодження певних ситуацій стає дещо складнішим. Але, маючи на увазі , я не бачу нічого технічно неправильного в тому, щоб також обробляти транзакції на рівні додатків під час створення єдиної процедуридзвінок; знову ж таки, один оператор DML є власною транзакцією і не потребує явної обробки транзакцій на будь-якому рівні.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.