在集合中找不到参数'?user_email'

时间:2015-11-28 14:25:15

标签: c# mysql asp.net visual-studio prepared-statement

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

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()块并生成一个异常:

Parameter '?user_email' not found in the collection.

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

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

2 个答案:

答案 0 :(得分:1)

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并检查是否获得了一些返回值

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

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

答案 1 :(得分:1)

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