Как использовать SqlTransaction для нескольких методов

Давайте предположим, что у нас есть Объект A, который может быть удален Объектом B, который содержит клавишу A от A

Если вы хотите удалить A, сначала вы должны удалить переднюю клавишу из B, а затем вы можете удалить A, но если что-то пойдет не так, ее следует откатить, но я также хочу использовать независимую кнопку удаления из B, но в данный момент я не не знаю, как этого добиться

моя текущая идея:

    public void DeleteA(Object a)
    {
        using (SqlConnection con = new SqlConnection())
        {
            con.open();

            using (SqlTransaction tr = con.BeginTransaction())
            {
                try
                {
                    DeleteAfromAllB(a, con, tr);

                    using (SqlCommand cmd = new SqlCommand("STP_A_Delete", con))
                    {
                        cmd.Transaction = tr;

                        // some parameters
                        // some sort of Execute
                        // e.g.: cmd.ExecuteNonQuery();
                    }
                    tr.Commit();
                }
                catch (SqlException ex)
                {
                    //ExceptionHandling
                }
            }
        }
    }

    private void DeleteAfromAllB(Object a, SqlConnection con, SqlTransaction tr)
    {
        try
        {
            using (SqlCommand cmd = new SqlCommand("STP_B_Delete_Referenc_To_A", con))
            {
                cmd.Transaction = tr;

                // some parameters
                // some sort of Execute
                // e.g.: cmd.ExecuteNonQuery();
            }
        }
        catch (SqlException ex)
        {
            //ExceptionHandling
        }
    }       

    public void DeleteAfromAllB(Object a)
    {
        using (SqlConnection con = new SqlConnection())
        {
            con.open();

            using (SqlTransaction tr = con.BeginTransaction())
            {
                DeleteAfromAllB(a,con,tr);

                tr.Commit();
            }
        }
    }

но, как вы можете видеть, это довольно некрасиво

1 ответ

Решение

Вызов

public void DeleteAfromAllB(Object a) 

не нужно передавать SqlConnection, так как вы можете ссылаться на tr.Connection. Так что вам просто нужно SqlTransaction в качестве параметра. Итак, для вашего первоначального вопроса, да, я думаю, что передача в SqlTransaction - это путь. Лично я предпочитаю этот способ, потому что вы можете легко отслеживать стек вызовов / объем транзакции (то есть, где транзакция началась / закончилась).

Другой альтернативой является использование TransactionScope.

Например

private void DeleteAfromAllB(Object a)
{
    try
    {
        using (var con = new SqlConnection())
        {
            con.open();
            using (var cmd = new SqlCommand("STP_B_Delete_Referenc_To_A", con))
            {
                // some parameters
                // some sort of Execute
                // e.g.: cmd.ExecuteNonQuery();
            }
        }
        catch (SqlException ex)
        {
            //ExceptionHandling
        }
    }
}

public void DeleteAfromAllB_TopLevel(Object a)
{
    using (var scope = new TransactionScope())
    {
        DeleteAfromAllB(a);

        // The Complete method commits the transaction. If an exception has been thrown, 
        // Complete is not  called and the transaction is rolled back.
        scope.Complete();
    }
}
Другие вопросы по тегам