在C#中使用Prepared语句与Mysql

我在我的程序中尝试了准备好的声明,但没有工作。

评论的部分是Prepared Statement部分。 当我将其改为正常陈述时,一切都是正确的。

有人能告诉我我错过了什么吗?

非常感谢。

private void btnLogin_Click(object sender, EventArgs e) { MySqlCommand cmd = MySqlConn.cmd; //cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username='@val1' AND admin_password=PASSWORD('@val2')", MySqlConn.conn); //cmd.Prepare(); //cmd.Parameters.AddWithValue("@val1", tboxUserName.Text); //cmd.Parameters.AddWithValue("@val2", tboxPassword.Text); cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username='"+tboxUserName.Text+"' AND admin_password=PASSWORD('"+tboxPassword.Text+"')", MySqlConn.conn); MySqlDataReader res = cmd.ExecuteReader(); if (!res.HasRows) { MessageBox.Show("Error! "); res.Close(); return; } else { //do something } res.Close(); } 

尝试从查询中删除'并在添加参数后使用Prepare

 cmd = new MySqlCommand("SELECT * FROM admin WHERE admin_username=@val1 AND admin_password=PASSWORD(@val2)", MySqlConn.conn); cmd.Parameters.AddWithValue("@val1", tboxUserName.Text); cmd.Parameters.AddWithValue("@val2", tboxPassword.Text); cmd.Prepare(); 

您的解决方案几乎是正确的。 然而,由于这是一个登录过程,因此是一个面向安全的任务,我还想提出一些建议。

首先,考虑使按钮事件处理程序如下所示:

 private void btnLogin_Click(object sender, EventArgs e) { if (Login(tboxUserName.Text, tboxPassword.Text)) { // Log in was successful, do something... } else { // Log in was NOT successful, inform the user... } } 

这将使应用程序的维护和可读性更容易。 然后声明一个名为Login()的函数来执行繁重的工作:

 private bool Login(string username, string password) { try { MySqlCommand cmd = MySqlConn.cmd; cmd = new MySqlCommand( "SELECT count(*) FROM admin " + "WHERE admin_username=@username " + "AND admin_password=PASSWORD(@passwd)", MySqlConn.conn); cmd.Prepare(); cmd.Parameters.AddWithValue("@username", username); cmd.Parameters.AddWithValue("@passwd", password); int result = (int)cmd.ExecuteReader(); // Returns true when username and password match: return (result > 0); } catch (Exception e) { // Optional: log exception details // Deny log in if an error has occurred: return false; } } 

你会在这里注意到一些事情。 首先,从原始查询字符串中删除了引号,这些引号阻止命名参数正常工作。 此外,查询返回count()函数结果,而不是尝试创建包含管理员用户名和密码的结果集。 最后,该方法封装在try-catch块中,这样在发生错误的情况下,该方法返回false并拒绝登录。 我还将查询分解为串联字符串,以便于阅读。