Отправка нескольких команд 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();
});
}