2009-03-06 2 views
2
  1. У меня SQL Server 2000, он не поддерживает MultipleActiveResults.
  2. Мне нужно сделать несколько вставок, и это делается с одним подключением для каждой вставки.
  3. Я хочу начать транзакцию перед всеми вставками и закончить ее после всех вставок.
  4. Как это сделать?
+2

Вы можете разместить некоторые из кода, я получаю, что 2k не поддерживает MultipleActiveResults, но что имеет значение только для одновременных партий на вы можете, конечно, иметь несколько исполнений с объектом команды в данном соединении. – cmsjr

+0

Jader, я согласен с Cmsjr, ядром, проверенным с помощью SQL 8.00.194. Ваш код может быть конкретным, но тогда нам нужна дополнительная информация. –

ответ

1

В чем причина того, что вы не используете одно соединение и несколько команд (на самом деле одна команда воссоздана в цикле)? Может быть, это решение будет работать для вас:

public static void CommandExecNonQuery(SqlCommand cmd, 
     string query, SqlParameter[] prms) 
    { 
     cmd.CommandText = query; 
     cmd.Parameters.AddRange(prms); 
     cmd.ExecuteNonQuery(); 
     cmd.Parameters.Clear(); 
    } 

    static void Main(string[] args) 
    { 
     string insertQuery = 
      @"INSERT TESTTABLE (COLUMN1, COLUMN2) " + 
      "VALUES(@ParamCol1, @ParamCol2)"; 
     using (SqlConnection connection = 
      new SqlConnection(connectionString)) 
     { 
      using (SqlCommand command = 
       connection.CreateCommand()) 
      { 
       SqlTransaction transaction = null; 
       try 
       { 
        // BeginTransaction() Requires Open Connection 
        connection.Open(); 

        transaction = connection.BeginTransaction(); 

        // Assign Transaction to Command 
        command.Transaction = transaction; 
        for (int i = 0; i < 100; i++) 
         CommandExecNonQuery(command, insertQuery, 
          new SqlParameter[] { 
          new SqlParameter("@ParamCol1", i), 
          new SqlParameter("@ParamCol2", i.ToString()) }); 
        transaction.Commit(); 
       } 
       catch 
       { 
        transaction.Rollback(); 
        throw; 
       } 
       finally 
       { 
        connection.Close(); 
       } 
      } 
     } 
    } 

Также см
Sql Server Transactions - ADO.NET 2.0 - Commit and Rollback - Using Statement - IDisposable

+0

Я думаю, что это невозможно на Sql Server 2000. –

+0

Было бы лучше избавиться от SqlTransaction с помощью оператора using, а не от явного catch/finally. Устранение транзакции возвращает ее, если она не была выполнена. – Joe

+0

Возможно, Jader. Я тестировал его с помощью SQL 8.00.194 –

4

Вы не указали, используете ли вы .NET 2.0, но я сделаю это предположение. C# 3.0 Пример кода приведен ниже:

using (var tx = new TransactionScope()) { 
    // Execute multiple DB statements inside here 
    ts.Complete(); 
} 

Если какой-либо из операторов БД не получится, ts.complete никогда не будет достигнута, и сделка будет откат автоматически в конце с помощью заявления. Тем не менее, один из подходов к этому подходу заключается в том, что вы в конечном итоге используете DTC, если используете несколько соединений, что означает более низкую производительность.

Отредактировано изменить SqlTransaction к TransactionScope

Пример принуждать одно подключение к SQL, чтобы избежать использования кода неисправности:

using (var tx = new TransactionScope()) 
using (var db = new SqlConnection(connString)) { 
    // Command 1 
    using (var cmd = db.CreateCommand()) { 
     cmd.CommandText = "select..."; 
     using (var reader = cmd.ExecuteReader()) { 
      // Process results or store them somewhere for later 
     } 
    } 

    // Command 2 
    using (var cmd = db.CreateCommand()) { 
     cmd.CommandText = "select..."; 
     using (var reader = cmd.ExecuteReader()) { 
      // Process results or store them somewhere for later 
     } 
    } 

    // Command 3 
    using (var cmd = db.CreateCommand()) { 
     cmd.CommandText = "select..."; 
     using (var reader = cmd.ExecuteReader()) { 
      // Process results or store them somewhere for later 
     } 
    } 
    tx.Complete(); 
} 
+0

любая альтернатива нескольким соединениям в Sql Server 2000? Я знаю, что Sql Server 2005 поддерживает M.A.R.S, но 2000 нет. –

+0

Нет публичного конструктора для SqlTransaction. Единственный способ создать экземпляр - использовать метод SqlConnection.BeginTransaction, который не является статичным. –

+0

@Jader: Вы правы, я хотел использовать TransactionScope. Сообщение отредактировано. – Chris

0

Я не думаю, что транзакция может охватывать несколько соединений.

В чем причина многократных вставок в отдельных соединениях? Я думаю, вы бы хотели, чтобы они были в одном соединении нормально.

+0

Sql Server 2000 не поддерживает MultipleActiveResultSets. Поэтому мне пришлось создать соединение для каждой вставки. –

+1

@JaderDias MARS не требуется для повторного использования одного IDbConnection с несколькими 'IDbCommand'.Фактически, если вы используете SqlClient, пул соединений ADO эффективно заставит вас повторно использовать одно и то же соединение с базой данных, даже если ваш код окажется закрытым и снова откроет соединение. – binki

1

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

+0

Желание OP невозможно. – Cheeso

Смежные вопросы