无法访问SqlTransaction对象以在catch块中回滚

Mar*_*rks 33 c# sql ado.net transactions rollback

我遇到了问题,我发现的所有文章或例子似乎都不关心它.

我想在事务中执行一些数据库操作.我想做的与大多​​数例子非常相似:

using (SqlConnection Conn = new SqlConnection(_ConnectionString))
{
    try
    {
        Conn.Open();
        SqlTransaction Trans = Conn.BeginTransaction();

        using (SqlCommand Com = new SqlCommand(ComText, Conn))
        {
            /* DB work */
        }
    }
    catch (Exception Ex)
    {
        Trans.Rollback();
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

但问题是SqlTransaction Transtry块内声明了.所以它在catch()块中是不可访问的.大多数例子只是在阻止之前Conn.Open()Conn.BeginTransaction()之前try,但我认为这有点风险,因为两者都可以抛出多个异常.

我错了,还是大多数人都忽略了这种风险?如果发生异常,什么是能够回滚的最佳解决方案?

Dav*_*kle 56

using (var Conn = new SqlConnection(_ConnectionString))
{
    SqlTransaction trans = null;
    try
    {
        Conn.Open();
        trans = Conn.BeginTransaction();

        using (SqlCommand Com = new SqlCommand(ComText, Conn, trans))
        {
            /* DB work */
        }
        trans.Commit();
    }
    catch (Exception Ex)
    {
        if (trans != null) trans.Rollback();
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

或者你可以更清洁,更轻松地使用它:

using (var Conn = new SqlConnection(_ConnectionString))
{
    try
    {
        Conn.Open();
        using (var ts = new System.Transactions.TransactionScope())
        {
            using (SqlCommand Com = new SqlCommand(ComText, Conn))
            {
                /* DB work */
            }
            ts.Complete();
        }
    }
    catch (Exception Ex)
    {     
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)


Mik*_*sov 8

我不喜欢键入类型并将变量设置为null,因此:

try
{
    using (var conn = new SqlConnection(/* connection string or whatever */))
    {
        conn.Open();

        using (var trans = conn.BeginTransaction())
        {
            try
            {
                using (var cmd = conn.CreateCommand())
                {
                    cmd.Transaction = trans;
                    /* setup command type, text */
                    /* execute command */
                }

                trans.Commit();
            }
            catch (Exception ex)
            {
                trans.Rollback();
                /* log exception and the fact that rollback succeeded */
            }
        }
    }
}
catch (Exception ex)
{
    /* log or whatever */
}
Run Code Online (Sandbox Code Playgroud)

如果你想切换到MySql或其他提供商,你只需要修改1行.


Ita*_*aro 6

用这个

using (SqlConnection Conn = new SqlConnection(_ConnectionString))
{
    SqlTransaction Trans = null;
    try
    {
        Conn.Open();
        Trans = Conn.BeginTransaction();

        using (SqlCommand Com = new SqlCommand(ComText, Conn))
        {
            /* DB work */
        }
    }
    catch (Exception Ex)
    {
        if (Trans != null)
            Trans.Rollback();
        return -1;
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句 - 你没有在成功处理的情况下提交它