The variable name '@' has already been declared. Variable names must be unique within a query batch or stored procedure. in c#

北慕城南 提交于 2019-12-18 04:55:16

问题


The variable name '@LockState' has already been declared. Variable names must be unique within a query batch or stored procedure.

When I execute this code below, above error comes on my sql parameters on second @LockState.

private void btn_lock2_Click(object sender, EventArgs e)
{
  rwd.command = new SqlCommand();
  rwd.command.Connection = rwd.connection;

  try
  {
    if ((txt2.Text == "")| (txt_desc2.Text == ""))
      appMessages.unCompleteFields();
    else
    {
      long from = long.Parse(this.txt2.Text);
      long to = long.Parse(this.txt3.Text);
      if (from <= to)
      {
        for (long counter = from; counter <= to; counter++) 
        {
          string upd = "update card set LockState=@lockstate,
          card_descr=@card_descr where [cardNumber] = N'{0}'";
          rwd.command.CommandText = upd;
          rwd.command.Parameters.Add(new SqlParameter("@LockState",
          SqlDbType.NVarChar)).Value =1;
          rwd.command.Parameters.Add(new SqlParameter("@card_descr",
          SqlDbType.NVarChar)).Value = txt_desc2.Text;
          rwd.connection.Open();
          rwd.command.ExecuteScalar();
          rwd.connection.Close();
        }
      appMessages.successfulyUpdated();
      }
      else
      {
        appMessages.unsuccessfulyUpdated();
      }
      this.txt1.Text = "";
      this.txt2.Text = "";
    }
  }
  catch (Exception exp) { throw exp; }
  }
}

回答1:


You are adding multiple times the same parameters in every iteration of loop.

Add rwd.command.Parameters.Clear() after each loop iteration:

for (long counter = from; counter <= to; counter++)
{
    rwd.command.Parameters.Clear();

    string upd = "update card set LockState=@lockstate, card_descr=@card_descr where [cardNumber] = N'{0}'";
    rwd.command.CommandText = upd;
    rwd.command.Parameters.Add(new SqlParameter("@LockState",
    SqlDbType.NVarChar)).Value =1;
    rwd.command.Parameters.Add(new SqlParameter("@card_descr",
    SqlDbType.NVarChar)).Value = txt_desc2.Text;
    rwd.connection.Open();
    rwd.command.ExecuteScalar();
    rwd.connection.Close();
}

or add parameter before loop:

rwd.command.Parameters.Add(new SqlParameter("@LockState", SqlDbType.NVarChar));
rwd.command.Parameters.Add(new SqlParameter("@card_descr", SqlDbType.NVarChar));

and then in loop:

for (long counter = from; counter <= to; counter++)
{
    string upd = "update card set LockState=@lockstate,
    card_descr=@card_descr where [cardNumber] = N'{0}'";
    rwd.command.CommandText = upd;

    rwd.command.Parameters["@LockState"].Value =1;
    rwd.command.Parameters["@card_descr"].Value = txt_desc2.Text;

    rwd.connection.Open();
    rwd.command.ExecuteScalar();
    rwd.connection.Close();
}



回答2:


since you share the command in each iteration clear the parameters at the beginning of the loop.

for (long counter = from; counter <= to; counter++) 
{
  rwd.command.Parameters.Clear();

But I would only set the value in the loop by defining it before the loop as below

rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);

for (long counter = from; counter <= to; counter++) 
{
    rwd.command.Parameters["@LockState"].Value = 1;
    rwd.command.Parameters["@card_descr"].Value = txt_desc2.Text;
    // ...
}

Side Note:

you have [cardNumber] = N'{0}'" but never set value for that. you better use parameter for the cardNumber as well.




回答3:


My answer is basically an extension to other two existing answers (from @gzaxx and @Damith), which both are correct.
You do use the same SqlCommand instance in each loop iteration, so you do not have to (and should not) perform any initialization operations in the loop.
What others already wrote is that adding parameters' definitions in the loop is the cause of your issue, as in result you are trying to define each of the parameters as many times, as the loop iterates.
What I think you should also consider, is also moving other code out of the loop, which basically means removing this from inside the loop:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
rwd.command.Parameters.Add(new SqlParameter("@LockState", SqlDbType.NVarChar)).Value =1;
rwd.command.Parameters.Add(new SqlParameter("@card_descr", SqlDbType.NVarChar)).Value = txt_desc2.Text;
rwd.connection.Open();

and placing its equivalent before the loop:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
SqlParameter lockStateParam = rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
SqlParameter cardDescrParam = rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);
rwd.connection.Open();

You'd also need to replace the way you set parameter values, placing this in the loop, instead of the removed code:

lockStateParam.Value = 1;
cardDescrParam.Value = txt_desc2.Text;

As we moved opening the connection out of the loop, we also need to move the connection closing operation outside of the loop, so this instructions goes out:

rwd.connection.Close();

The entire operation gives us this code block:

string upd = "update card set LockState=@lockstate,
card_descr=@card_descr where [cardNumber] = N'{0}'";
rwd.command.CommandText = up
SqlParameter lockStateParam = rwd.command.Parameters.Add("@LockState",SqlDbType.NVarChar);
SqlParameter cardDescrParam = rwd.command.Parameters.Add("@card_descr",SqlDbType.NVarChar);
rwd.connection.Open();
for (long counter = from; counter <= to; counter++) 
{
  lockStateParam.Value = 1;
  cardDescrParam.Value = txt_desc2.Text;
  rwd.command.ExecuteScalar();
}
rwd.connection.Close();

When looking further at this, I see, that each iteration actually uses the very same values for the parameters, so - if it's not a result of simplifying the code for StackOverflow - it means that you basically execute the very same update over and over again.
I'd assume that it actually is a simplified code, as (just as @Damith noted) you seem to be filtering the updated rows by cardNumber column. What seems a bit strange in that, is that you are apparently using string formatting, to replace the {0} placeholder with a text. If it's so, then you do have to set the CommandText attribute inside the loop, but I'd rather consider doing what @Damith suggested, so adding a third command parameter for that purpose.

On a side-note: If the answers provided work for you (and basically all given should), consider accepting one of those (probably the first one that appeared here).




回答4:


Use rwd.command.ExecuteScalar(); rwd.command.Parameters.clear();



来源:https://stackoverflow.com/questions/19535486/the-variable-name-has-already-been-declared-variable-names-must-be-unique-w

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!