【问题标题】:System.Data.SqlClient.SqlException: 'Must declare the scalar variable "@ID".' [duplicate]System.Data.SqlClient.SqlException:'必须声明标量变量“@ID”。' [复制]
【发布时间】:2018-04-11 20:04:40
【问题描述】:

我不断收到错误消息

System.Data.SqlClient.SqlException: '必须声明标量变量“@ID”。' -

我有一个gridview,它可以捕获用户在文本框中输入的内容,并通过单击按钮将它们提交到数据库。当用户单击按钮时,我还尝试将当前登录的用户存储到数据库表中。有人可以帮助我了解为什么此消息不断出现吗?

这是我的按钮单击事件的 C# 代码

protected void btnSubmit_Click(object sender, EventArgs e)
{
    string query = "insert into Stock_Take_Item(ItemID, BarQuantity, StorageQuantity) values(@ID, @BAR, @STORAGE); insert into Stock_Take(Username, StockDate)" +
            " values(@Username, GetDate())";

    SqlConnection con = new SqlConnection(connectionString);

    SqlCommand cmd = new SqlCommand(query, con);
    con.Open();

    cmd.Parameters.AddWithValue("@Username", Session["username"].ToString());

    foreach (GridViewRow row in gvStockTake.Rows)
    {
        Label ID = row.FindControl("itemId") as Label;
        TextBox BAR = row.FindControl("txtBar") as TextBox;
        TextBox STORAGE = row.FindControl("txtStorage") as TextBox;

        cmd.Parameters.Clear();

        cmd.Parameters.Add("@ID", SqlDbType.VarChar).Value = ID.Text;
        cmd.Parameters.Add("@BAR", SqlDbType.Int).Value = BAR.Text;
        cmd.Parameters.Add("@STORAGE", SqlDbType.Int).Value = STORAGE.Text;

        cmd.ExecuteNonQuery(); //query execution
    }

    con.Close();
    Response.Write("Successfully inserted stock take items.");
}

这是我在 C# 代码中登录的代码

protected void btnLogin_Click(object sender, EventArgs e)
{
    using (SqlConnection sqlCon = new SqlConnection(@"Data Source=(local)\;Initial Catalog=SmallBatch;Integrated Security=True;"))
    {
        sqlCon.Open();

        string query = "SELECT COUNT(1) FROM Site WHERE Username=@username AND Password=@password";

        SqlCommand sqlCmd = new SqlCommand(query, sqlCon);

        sqlCmd.Parameters.AddWithValue("@username", txtUsername.Text.Trim());
        sqlCmd.Parameters.AddWithValue("@password", txtPassword.Text.Trim());

        int count = Convert.ToInt32(sqlCmd.ExecuteScalar());

        if (count == 1)
        {
            Session["username"] = txtUsername.Text.Trim();
            Response.Redirect("Dashboard.aspx");
        }
        else 
        { 
            lblErrorMessage.Visible = true; 
        }
    }
}

我还是 ASP.NET 和 C# 的新手,所以任何建议都非常感谢!

【问题讨论】:

  • 而不是 cmd.Parameters.Clear(); 为什么不直接重置值呢?另外,你做cmd.Parameters.AddWithValue("@Username",... 然后你清除它
  • 您的查询包含两个不同的插入语句 - 我觉得这些应该单独执行?这可能是问题所在。
  • @jocull 不是真的。他可以做到。实际上,可能只是将参数收集到一个大块中,而不是单独执行单独的插入。这样一来,DB就只有一趟了。取决于,总负载有多大
  • SqlCommandSqlConnection 都是一次性的,所以都应该在 using 块中。连接的 Dispose(当它退出 using 块时)处理关闭,因此您不需要。我建议看看Can we stop using AddWithValue
  • 清除参数集合将清除您的用户名(在循环之前设置)。你是这个意思吗?

标签: c# asp.net


【解决方案1】:

我会批量处理 - 它会减少访问数据库的次数

protected void btnSubmit_Click(object sender, EventArgs e)
{

    var counter = 0;
    var query = @"insert into Stock_Take_Item
                  (ItemID, BarQuantity, StorageQuantity)
                  values
              ({1}, {2}, {3});
               insert into Stock_Take
               (Username, StockDate) 
               values
               ({0}, GetDate());";

    var paramList = new List<SqlParameter>();
    var sqlBulk = new StringBuilder(10000);
    var p0 = "@0";
    var maxRows = 100;
    var currRow = 0;
    var totalRows = 0;

    foreach (GridViewRow row in gvStockTake.Rows)
    {
        Label ID = row.FindControl("itemId") as Label;
        TextBox BAR = row.FindControl("txtBar") as TextBox;
        TextBox STORAGE = row.FindControl("txtStorage") as TextBox;

        currRow++;        
        totalRows++;

        if (counter == 0)
        {
            paramList.Add(new SqlParameter(, Session["username"].ToString()));            
        }
        var p1 = "@" + ++counter;
        var p2 = "@" + ++counter;
        var p3 = "@" + ++counter;

        paramList.AddRange(new[]{
            new SqlParameter(p1, Convert.ToInt32(Id.Text),
            new SqlParameter(p2, Convert.ToInt32(BAR.Text),
            new SqlParameter(p3, Convert.ToInt32(STORAGE.Text)
            });

        sqlBulk.AppendFormat(query, p0, p1, p2, p3);

        if (currRow == maxRows || totalRows == gvStockTake.Rows)
        {
            using (var con = new SqlConnection(connectionString))
            {
                using (var cmd = new SqlCommand(sqlBulk.ToString(), con))
                {
                    cmd.Parameters.AddRange(paramList);
                    con.Open();
                    cmd.ExecuteNonQuery();
                }
            }
            currRow = 0;
            counter = 0;
            paramList.Clear();
            sqlBulk.Length = 0;
        }

    }

}

免责声明:未经测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-28
    • 2020-10-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多