C # SQL Вставка с надписью «дубликат переменной»

Предполагается, что приведенный ниже код перебирает список компонентов и вставляет их для конкретного перечня материалов. Код выполняет цикл один раз, а затем отправляет сообщение об ошибке,

Имя переменной '@product' уже объявлено. Имена переменных должны быть неизменными в пакете запроса или хранимой процедуре.

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

Должен ли я просто перенести foreach за пределы второго оператора using ?

public static void insert_rework(string product, List<string> component_list, string sn, DateTime today, string connectionString)
{
    string sql = 
      @"INSERT INTO table (
          Product, 
          Component, 
          Serial_Num, 
          Cur_Date) 
        VALUES (
          @product, 
          @component, 
          @sn, 
          @date)";

    using (SqlConnection connection = new SqlConnection(connectionString))
    using (SqlCommand command = new SqlCommand(sql, connection))
    {
        connection.Open();
        foreach (string component in component_list)
        {
            command.Parameters.AddWithValue("@product", product);
            command.Parameters.AddWithValue("@component", component);
            command.Parameters.AddWithValue("@sn", sn);
            command.Parameters.AddWithValue("@date", today);
            try
            {
                command.ExecuteNonQuery();
            }
            catch (SqlException sq)
            {
                Console.WriteLine(sq.Message);
            }
        }
    }
}

Всего 2 ответа


У вас есть вызовы AddWithValue внутри цикла foreach. Конечно, это означает, что в каждом цикле вы читали одни и те же параметры с разными значениями.

Как насчет объявления их вне цикла и просто изменения значения внутри цикла

   command.Parameters.Add("@product", SqlDbType.NVarChar);
   command.Parameters.Add("@component", SqlDbType.NVarChar);
   command.Parameters.Add("@sn", SqlDbType.NVarChar);
   command.Parameters.Add("@date", SqlDbType.Date);       
   foreach (string component in component_list)
   {
       command.Parameters["@product"].Value = product;
       command.Parameters["@component"].Value = component;
       command.Parameters["@sn"].Value = sn;
       command.Parameters["@date"].Value = today;
       .....

Конечно, вы можете использовать Clear, чтобы удалить любой параметр из коллекции, но это кажется ненужным. Кроме того, некоторые значения, кажется, никогда не меняются внутри цикла. Эти значения могут быть добавлены вне цикла только один раз.

   command.Parameters.Add("@product", SqlDbType.NVarChar);
   command.Parameters.Add("@component", SqlDbType.NVarChar).Value = component;
   command.Parameters.Add("@sn", SqlDbType.NVarChar).Value = sn;
   command.Parameters.Add("@date", SqlDbType.Date).Value = today;       
   foreach (string component in component_list)
   {
       command.Parameters["@component"].Value = component;
       command.ExecuteNonQuery();
   }

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


Вы добавляете один и тот же параметр каждый раз в цикл foreach. Либо очистите параметры перед их добавлением, либо проверьте существование и выполните соответствующие действия:

if (command.Parameters.Contains("@product"))
    command.Parameters["@product"].Value = product;
else
    command.Parameters.AddWithValue("@product", product);

Есть идеи?

10000