在集合中找不到参数“?user_email”

Parameter '?user_email' not found in the collection

我正在使用 MySql 5.6x 和 Visual Studio 2015,windows 10,64 位。 C# 作为编程语言。在我的 CRUD.cs(Class 文件)中,我创建了以下方法:

public bool dbQuery(string sql,string[] paramList= null)
{
    bool flag = false;
    try
    {
        connect();
        cmd = new MySqlCommand(sql,con);
        cmd.Prepare();
        if(paramList != null){ 
         foreach(string i in paramList){
                string[] valus = i.Split(',');
                string p = valus[0];
                string v = valus[1];
                cmd.Parameters[p].Value = v;
            }
         }
        if (cmd.ExecuteNonQuery() > 0)
        {
            flag = true;
        }
    }
    catch (Exception exc)
    {
        error(exc);
    }
   }

我像这样传递查询和参数列表:

  protected void loginBtn_Click(object sender, EventArgs e)
  {
    string sql = "SELECT * FROM dept_login WHERE (user_email = ?user_email OR user_cell = ?user_cell) AND userkey = ?userkey";
    string[] param = new string[] {
         "?user_email,"+ userid.Text.ToString(),
         "?user_cell,"+ userid.Text.ToString(),
         "?userkey,"+ userkey.Text.ToString()
    };
    if (db.dbQuery(sql, param))
    {
        msg.Text = "Ok";
    }
    else
    {
        msg.Text = "<strong class='text-danger'>Authentication Failed</strong>";
    }
  }

现在的问题是,循环迭代完成后,直接跳转到catch()块,产生了一个Exception:

Parameter '?user_email' not found in the collection.

我发送这样的参数是否正确?还有其他方法可以做同样的事情吗? 谢谢

编辑:我认为最好的方法可能是二维数组来收集参数及其值,然后在方法中循环以获取 cmd.AddWidthValues() 中的参数?我可能错了...

在您的 dbQuery 中,您没有使用预期名称创建参数集合,因此当您尝试为不符合预期名称的参数设置值时会出现错误存在

public bool dbQuery(string sql,string[] paramList= null)
{
    bool flag = false;
    try
    {
        connect();
        cmd = new MySqlCommand(sql,con);
        cmd.Prepare();
        if(paramList != null){ 
            foreach(string i in paramList){
                string[] valus = i.Split(',');
                string p = valus[0];
                string v = valus[1];
                cmd.Parameters.AddWithValue(p, v);
            }
        }
        if (cmd.ExecuteNonQuery() > 0)
           flag = true;
    }
    catch (Exception exc)
    {
        error(exc);
    }
}

当然,这将添加数据类型等于字符串的每个参数,因此如果您的数据表列不是字符串类型,则很容易出错

更好的方法是这个

List<MySqlParameter> parameters = new List<MySqlParameter>()
{
   {new MySqlParameter() 
        { 
           ParameterName = "?user_mail", 
           MySqlDbType= MySqlDbType.VarChar,
           Value = userid.Text
         },
   {new MySqlParameter() 
        { 
           ParameterName = "?user_cell", 
           MySqlDbType= MySqlDbType.VarChar,
           Value = userid.Text
         },

   {new MySqlParameter() 
        { 
           ParameterName = "?userkey", 
           MySqlDbType = MySqlDbType.VarChar,
           Value = userkey.Text
         },

}
if (db.dbQuery(sql, parameters))
 ....

并在 dbQuery 中接收列表,将其添加到参数集合中

public bool dbQuery(string sql, List<MySqlParameter> paramList= null)
{
    bool flag = false;
    try
    {
        connect();
        cmd = new MySqlCommand(sql,con);
        cmd.Prepare();
        if(paramList != null)
         cmd.Parameters.AddRange(paramList.ToArray());

        if (cmd.ExecuteNonQuery() > 0)
        {
            flag = true;
        }
    }
    catch (Exception exc)
    {
        error(exc);
    }
}

顺便说一下,与您的实际问题无关,但您的代码似乎没有关闭和处理连接。这将导致诊断和修复非常棘手的问题。尝试使用 using 语句并避免使用全局连接变量

编辑 正如您所注意到的 ExecuteNonQuery 不适用于 SELECT 语句,您需要使用 ExecuteReader 并检查是否获得了一些 return 值

    using(MySqlDataReader reader = cmd.ExecuteReader())
    {
        flag = reader.HasRows;
    }

这当然意味着当您想插入、更新或删除记录时您会遇到麻烦,而您需要 ExecuteNonQuery。创建通用函数来处理不同类型的查询非常困难,不值得进行所需的工作和调试。最好使用一些众所周知的 ORM 软件,例如 EntityFramework 或 Dapper。

您的 SQL 命令的参数集合不包含这些参数,因此您不能以这种方式对它们进行索引: cmd.Parameters[p].Value = v; 您需要以这种方式将它们添加到命令的参数集合中:cmd.Parameters.AddWithValue(p, v);.