SqlTransaction.Commit()之前的SqlCommand.Dispose()?

时间:2012-02-15 16:55:58

标签: c# .net sql-server-2008 tsql

在提交事务之前,是否可以处理分配给事务的命令?我自己测试了以下代码,它似乎运行良好,但这是一个相当小的例子,所以如果有人肯定知道我正在寻找确认。

internal static void TestTransaction()
{
    try
    {
        Program.dbConnection.Open();
        using (SqlTransaction transaction = Program.dbConnection.BeginTransaction())
        {
            Boolean doRollback = false;
            for (int i = 0; i < 10; i++)
            {
                using (SqlCommand cmd = new SqlCommand("INSERT INTO [testdb].[dbo].[transactiontest] (testvalcol) VALUES (@index)", Program.dbConnection, transaction))
                {
                    cmd.Parameters.AddWithValue("@index", i);
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (SqlException)
                    {
                        doRollback = true;
                        break;
                    }
                }
            }
            if (doRollback)
                transaction.Rollback();
            else
                transaction.Commit();
        }
    }
    finally
    {
        Program.dbConnection.Close();
    }
}

3 个答案:

答案 0 :(得分:13)

连接,事务和命令对象只是将命令发送到数据库的工具。执行命令后,数据库已收到该命令。无论你以后如何处理命令对象,将其丢弃,焚烧或射向月球,这一事实都不会改变。 (它只能回滚)。

您可以在一个SqlConnection(包含或不包含SqlTransaction)的范围内创建和配置任意数量的命令。您可以在一个SqlConnection内开始和处理任意数量的交易。为了证明这一点,请参阅:

using (var conn = new SqlConnection(@"server=(local)\sql2008;database=Junk;Integrated Security=SSPI"))
{
  conn.Open();
  // Repeat this block as often as you like...
  using (var tran = conn.BeginTransaction())
  {
    using (var cmd = new SqlCommand("INSERT INTO Mess VALUES ('mess1')", conn, tran))
    {
      cmd.ExecuteNonQuery(); // Shows in Sql profiler
    }
    tran.Commit(); // Commits
  }
  using (var cmd = new SqlCommand("INSERT INTO Mess VALUES ('mess2')", conn))
  {
    cmd.ExecuteNonQuery(); // Executes and commits (implicit transaction).
  }
}

当然,对于健康的代码,您需要以正确的顺序处理所有对象。处置SqlConnection后处置命令可能会导致连接对象留在内存中。

答案 1 :(得分:1)

是的,它可能是安全的。 using()正在关闭Command,而不是Connection。

但是你应该将该Connection放在另一个using()块或try / finally构造中。

答案 2 :(得分:1)

确认,这种方法非常有效(至少在我们公司这里)甚至被认为是正确的方法。

  1. 创建连接
  2. 创建交易
  3. 创建命令,使用事务,执行
  4. dispose command(s)
  5. 提交交易
  6. 配置连接