Reputation: 687
The code below is supposed to iterate through a list of components and insert them for a specific bill of materials. The code executes the loop once, and then sends out an error message,
The variable name '@product' has already been declared. Variable names must be unqiue within a query batch or stored procedure.
Im not sure the best way to change this or why this is being thrown. Any thoughts?
Would I just have to move the foreach outside of the second using
statement?
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);
}
}
}
}
Upvotes: 1
Views: 390
Reputation: 216273
You have your AddWithValue calls inside the foreach loop. Of course this means that at each loop you readd the same parameters with different values.
What about declaring them outside the loop and just changing the value inside the loop
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;
.....
Of course you can use Clear to remove any parameter from the collection but this seems to be unneeded. Also, some values seems to never change inside the loop. These value could be added outside the loop just one time.
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();
}
Notice also that you should always use Add instead of AddWithValue because this method, while handy, is well known to hit the performances and sometime it can also give wrong results if the value passed to AddWithValue is not of the type expected by the underlying table. (localized strings instead of dates, localized strings instead of decimals,double,etc)
Upvotes: 2
Reputation: 3019
You are adding the same parameter every time in foreach loop. Either clear parameters before adding them or check existence and perform accordingly:
if (command.Parameters.Contains("@product"))
command.Parameters["@product"].Value = product;
else
command.Parameters.AddWithValue("@product", product);
Upvotes: 0