Отправка нескольких команд SQL в одной транзакции

У меня есть огромный список строк INSERT INTO .... В настоящее время я запускаю их с помощью:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();
    foreach (var commandString in sqlCommandList)
    {
        SqlCommand command = new SqlCommand(commandString, connection);
        command.ExecuteNonQuery();
    }
}

Я вижу, что каждый ExecuteNonQuery() также выполняет commit.

  • Есть ли способ вставить все строки в одну транзакцию (commit в конце)?
  • Я хочу, чтобы одна транзакция заключалась в том, чтобы ускорить процесс "вставки". Будет ли еще одна транзакция быстрее?

Ответ 1

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

    SqlTransaction trans; 

    try
    {
        SqlConnection connection = new SqlConnection(connectionString);
        connection.Open();

        trans = connection.BeginTransaction(); 

        foreach (var commandString in sqlCommandList)
        {
            SqlCommand command = new SqlCommand(commandString, connection,trans);
            command.ExecuteNonQuery();
        }

        trans.Commit(); 
    }
    catch (Exception ex) //error occurred
    {
        trans.Rollback();
        //Handel error
    }

Ответ 2

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

using (SqlConnection connection = new SqlConnection(connectionString))
{
   try
   {
      connection.Open();

      using (SqlTransaction trans = connection.BeginTransaction())
      {
          using (SqlCommand command = new SqlCommand("", connection,trans))
          {
             command.CommandType = System.Data.CommandType.Text;

             foreach (var commandString in sqlCommandList)
             {
                command.CommandText = commandString;
                command.ExecuteNonQuery();
             }
          }

          trans.Commit();
       }        
    }
    catch (Exception ex) //error occurred
   {
       //Handel error
   }
}

Ответ 3

Немного поздно, но если вы вставляете все значения в одну и ту же таблицу, введите SQL insert как "insert into tablex (f1, f2, f3,...) values ​​(@F1, @F2, @F3...)". Создайте команду и добавьте параметры @F1..., а затем установите флаг Prepare в команде. Теперь, когда вы зацикливаете свой список значений для вставки, вы можете установить их в соответствующие параметры, а затем выполнить ExecuteNonQuery. SQL будет предварительно разобрать командную строку один раз, а затем использовать новые параметры каждый раз. Это немного быстрее.

Наконец, вы можете выполнить несколько операторов SQL в одной команде, добавив ';' для каждого оператора, если вы должны выполнить всю строку. Вы можете объединить несколько этих команд вместе и сделать один запрос на сервер SQL для их выполнения.

Ответ 4

Вы можете просто объединить sql и позволить серверу обработать его:

using (SqlConnection connection = new SqlConnection(connectionString))
{
    string lsSql = string.Empty;
    foreach (var commandString in sqlCommandList)
    {
        lsSql = lsSql + commandString + " ; " + Environment.NewLine;
    }

    connection.Open();
    SqlCommand command = new SqlCommand(lsSql, connection);
    command.ExecuteNonQuery();
}

Ответ 5

Вы можете использовать Parallel для каждого

   using (SqlConnection connection = new SqlConnection(connectionString))
    {
        List<string> sqlCommandList = new List<string>();
        connection.Open();
        Parallel.ForEach(sqlCommandList, commandString =>
        {
            SqlCommand command = new SqlCommand(commandString, connection);
            command.ExecuteNonQuery();
        });
    }