SqlCommand.Dispose () перед SqlTransaction.Commit ()? - PullRequest
13 голосов
/ 15 февраля 2012

будет ли работать распоряжение командой, назначенной транзакции до ее фиксации?Я сам протестировал следующий код, и, похоже, он работал нормально, но это довольно небольшой пример, поэтому я ищу подтверждение, если кто-то точно знает.

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 ]

13 голосов
/ 15 февраля 2012

Объекты соединения, транзакции и команды - это просто средства для отправки команд в базу данных.После выполнения команды база данных получила ее.Что бы вы ни делали с командным объектом впоследствии, утилизируете его, сжигаете или стреляете в него на Луну, этот факт не меняется.(Откат возможен только).

Вы можете создавать и располагать столько команд, сколько захотите, в пределах одной SqlConnectionSqlTransaction или без него).И вы можете запускать и распоряжаться любым количеством транзакций в пределах одной 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 голос
/ 16 февраля 2012

Подтверждено, это работает очень хорошо и (по крайней мере, здесь, в нашей компании) даже считается правильным подходом.

  1. создать соединение
  2. создать транзакцию
  3. создать команду (и), использовать транзакцию, выполнить
  4. удалить команду (ы)
  5. зафиксировать транзакцию
  6. удалить соединение
1 голос
/ 15 февраля 2012

Да, это, вероятно, безопасно. using() закрывает Команду, а не Соединение.

Но вы должны поместить это Соединение в другой блок using() или в конструкцию try / finally.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...