变量名'@'已经声明。变量名在查询批处理或存储过程中必须是唯一的。在c#中

时间:2013-10-23 07:31:21

标签: c# sql sql-server visual-studio-2008

  

已声明变量名'@LockState'。变量   名称在查询批处理或存储过程中必须是唯一的。

当我执行下面的代码时,上面的错误出现在第二个@LockState上的sql参数上。

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; }
  }
}

6 个答案:

答案 0 :(得分:17)

在每次循环迭代中,您要添加多次相同的参数。

在每次循环迭代后添加rwd.command.Parameters.Clear()

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();
}

或在循环前添加参数:

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

然后循环:

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();
}

答案 1 :(得分:12)

因为你在每次迭代中共享命令,所以清除循环开头的参数。

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

但是我只会通过在循环之前定义它来设置循环中的值,如下所示

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;
    // ...
}

旁注:

你有[cardNumber] = N'{0}'"但从未为此设定价值。你最好也使用cardNumber的参数。

答案 2 :(得分:1)

我的答案基本上是对其他两个现有答案的延伸(来自@gzaxx和@Damith),两者都是正确的。
在每次循环迭代中都使用相同的SqlCommand实例,因此您不必(也不应该)在循环中执行任何初始化操作。
其他人已经写过的是在循环中添加参数的定义是导致问题的原因,因为在循环迭代时,你试图多次定义每个参数。 我认为你还应该考虑的是,还将其他代码移出循环,这基本上意味着从循环内部删除它:

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();

并在循环之前放置它的等价物:

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();

您还需要替换设置参数值的方式,将其置于循环中,而不是删除代码:

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

当我们将连接从循环中移开时,我们还需要在循环外部移动连接关闭操作,因此该指令熄灭:

rwd.connection.Close();

整个操作为我们提供了这个代码块:

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();

当进一步研究这个时,我看到,每个迭代实际上使用了相同的参数值,所以 - 如果它不是简化StackOverflow代码的结果 - 这意味着你基本上执行相同的更新并且一遍又一遍 我假设它实际上是一个简化的代码,因为(正如@Damith指出的那样)您似乎正在通过cardNumber列过滤更新的行。看起来有点奇怪的是,你显然是在使用字符串格式,用文本替换{0}占位符。如果是这样,那么你必须在循环中设置CommandText属性,但我宁愿考虑做@Damith所建议的,所以为此目的添加第三个命令参数。

旁注:如果所提供的答案对您有用(并且基本上都是给定的),请考虑接受其中一个(可能是此处出现的第一个)。

答案 3 :(得分:1)

使用     rwd.command.ExecuteScalar();     rwd.command.Parameters.clear();

答案 4 :(得分:1)

由于您在循环的最顶部使用循环命令(foreach、for 等...),因此请添加一个

rwd.Parameters.Clear();

这将在每次迭代时清除参数然后解决问题,我遇到了同样的错误,这解决了问题。

答案 5 :(得分:0)

我将rwd.Parameters.Clear();放入了循环,它解决了问题。