0

假设我们有一个可以删除的对象 A 一个持有来自 A 的前键的对象 B

如果要删除A,则必须先从B中删除forendkey,然后才能删除A,但如果出现问题,它应该回滚,但我也想独立使用B中的delete forendkey,但目前我没有不知道如何实现

我目前的想法:

    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();
            }
        }
    }

但是就像你看到的那样,这很丑

4

1 回答 1

1

通话

public void DeleteAfromAllB(Object a) 

不需要传递 SqlConnection,您可以从 tr.Connection 中引用。所以你只需要 SqlTransaction 作为参数。所以对于你原来的问题,是的,我认为传入 SqlTransaction 是要走的路。我个人更喜欢这种方式,因为您可以轻松跟踪事务的调用堆栈/范围(即事务开始/结束的位置)。

另一种选择是使用 TransactionScope。

例如

private void DeleteAfromAllB(Object a)
{
    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();
        }
    }
}

public void DeleteAfromAllB_TopLevel(Object a)
{
    using (var scope = new TransactionScope())
    {
        try
        {
            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();
        }
        catch (Exception)
        {
            //ExceptionHandling
        }
    }
}
于 2015-01-11T22:58:56.563 回答