Команда ExecuteNonQueryAsync sql выдает SP с несколькими наборами параметров в БД

#c# #sql #sql-server

#c# #sql #sql-сервер

Вопрос:

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

итак, по соображениям тестирования я создал цикл

 for (int i = 0; i < 10; i  )
{
    insert.Parameters.AddWithValue("@id", i);
    insert.Parameters.AddWithValue("@type", "test");

    insert.ExecuteNonQueryAsync();
}
  

Я запускаю это, и DB выдает это обратно, когда я выполняю трассировку.

 exec SP_Insert @id = 1, @type = 'test',@id = 2, @type = 'test',@id = 3, @type = 'test'
  

затем это не удается вставить, поскольку SP думает, что я передал его многим параметрам.

Есть ли какой-нибудь способ это исправить?

Ответ №1:

Добавьте await и убедитесь, что не добавляете новые параметры в каждый цикл.

При повторном использовании параметров, подобных приведенным ниже, вы должны установить правильный размер для параметра.

 insert.Parameters.Add("@id", SqlDbType.Int);
// Note: Set length of the target column. NVarChar -1 maps to nVarchar(max) 
insert.Parameters.Add("@type", SqlDbType.NVarChar, -1);

for (int i = 0; i < 10; i  )
{
    insert.Parameters["@id"].Value = i;
    insert.Parameters["@type"].Value = "test";

    await insert.ExecuteNonQueryAsync();
}
  

Комментарии:

1. Нет необходимости очищать параметры. Их можно использовать повторно. Добавьте их перед циклом и установите Value свойство внутри цикла.

2. @madreflection Хороший момент, я проверю это и изменю ответ, если это сработает..

3. спасибо вам обоим, это решило мою проблему и устранило ту же проблему, которая должна была возникнуть в функции, отличной от asyc.

4. @mobwar — Я бы также предложил сохранить объекты параметров, например var idParameter = insert.Parameters.Add("@id", ...); , а затем присвоить значение без индексации коллекции, например idParameter.Value = i;

Ответ №2:

Если вы можете вставлять данные непосредственно в таблицу или создавать промежуточную таблицу, гораздо быстрее будет использовать DataTable и BulkCopy вместо этого.

Таким образом, вы сначала загружаете данные в память клиента, а затем отправляете все строки за одну массовую операцию на SQL Server.

Хороший учебник, как это сделать, есть:

https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql/single-bulk-copy-operations

Использовать метод: WriteToServer(DataTable)

https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqlbulkcopy.writetoserver