C# MySqlCommand:未返回任何行

C# MySqlCommand:未返回任何行,c#,mysql,C#,Mysql,我在服务器中创建了一个数据库,并通过MySql查询浏览器添加了一行用于测试。该行在PhpMyAdmin或MySql查询浏览器中可见 但是当我想在程序中访问这个表时,它会告诉我没有行(reader.HasRows=false) cs是PublicVariables类中的连接字符串 这是密码 public static int checkuser(string myuser, string mypass) { try { using (MySq

我在服务器中创建了一个数据库,并通过MySql查询浏览器添加了一行用于测试。该行在PhpMyAdmin或MySql查询浏览器中可见

但是当我想在程序中访问这个表时,它会告诉我没有行(
reader.HasRows=false

cs是
PublicVariables
类中的连接字符串

这是密码

public static int checkuser(string myuser, string mypass)
{
        try
        {
            using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
            {
                string MypassMd5 = MakeMD5(mypass);
                conn.Open();

                if (conn == null)
                    Environment.Exit(0);

                using (MySqlCommand cmd =
                 new MySqlCommand("SELECT username, password " + "FROM Users WHERE username = 'myuser'" ,conn))
                {                        
                    using (MySqlDataReader reader = cmd.ExecuteReader())
                    {
                        //DateTime mytime = DateTime.Now  ;
                        if (reader.HasRows)
                        {
                            if (Convert.ToString(reader["password"]) != MypassMd5)
                            {
                                reader.Close();
                                conn.Close();
                                return -1;
                            }
                            else
                            {
                                PublicVariables.UserId = Convert.ToString(reader["username"]);
                                PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
                                conn.Close();
                                reader.Close();
                                return 1;
                            }
                        }
                        else
                        {
                            reader.Close();
                            conn.Close();
                            return 2;
                        }
                 }
            }            
       }
   }
   catch (MySqlException ex)
   {
       MessageBox.Show(ex.ToString());
   }

   return 0;
}

我的代码出了什么问题

我会尝试这样的
newmysqlcommand(“从username='myuser',conn的用户中选择username,password,userdegre”+”)

在select语句中添加userdegre列名称。

我会尝试类似这样的方法
新建MySqlCommand(“从username='myuser',conn的用户中选择username,password,userdegre”+)

将userdegre添加到select语句中的列名。

主要错误在命令字符串中,
myuser
是一个变量,不能将变量名放在引号内传递其值

new MySqlCommand("SELECT username, password FROM Users WHERE username = 'myuser'" ,conn)
相反,应将此行转换为使用参数化查询

string commandText = "SELECT username, password, userdegre FROM Users WHERE username = @uname"; 
using (MySqlCommand cmd = new MySqlCommand(commandText ,conn)
{
    cmd.Parameters.AddWithValue("@uname", myuser);
    ....
查看您的代码后,您会发现另一个错误。您试图读取字段
userdegre
,但您的查询无法检索该字段,因此需要将其添加到检索字段列表中。
但是您真正需要知道的唯一字段是
userdegre
,因为您已经知道用户名和密码,所以您可以删除datareader并使用ExecuteScalar并将用户名和密码作为WHERE子句的参数传递。如果您得到任何回报,那么您可以确保您的用户已通过数据库的身份验证

string commandText = "SELECT userdegre FROM Users WHERE username = @uname AND Password =@pwd";
using(MySqlCommand cmd = new MySqlCommand( commandText ,conn))
{                        
    cmd.Parameters.AddWithValue("@uname", myuser);
    cmd.Parameters.AddWithValue("@pwd", MypassMd5);
    var result = cmd.ExecuteScalar();
    if(result != null)
    {
          PublicVariables.UserId = myuser;
          PublicVariables.UserDegre = result.ToString();
    }
}

主要错误在命令字符串中,
myuser
是一个变量,不能将变量名放在引号内传递其值

new MySqlCommand("SELECT username, password FROM Users WHERE username = 'myuser'" ,conn)
相反,应将此行转换为使用参数化查询

string commandText = "SELECT username, password, userdegre FROM Users WHERE username = @uname"; 
using (MySqlCommand cmd = new MySqlCommand(commandText ,conn)
{
    cmd.Parameters.AddWithValue("@uname", myuser);
    ....
查看您的代码后,您会发现另一个错误。您试图读取字段
userdegre
,但您的查询无法检索该字段,因此需要将其添加到检索字段列表中。
但是您真正需要知道的唯一字段是
userdegre
,因为您已经知道用户名和密码,所以您可以删除datareader并使用ExecuteScalar并将用户名和密码作为WHERE子句的参数传递。如果您得到任何回报,那么您可以确保您的用户已通过数据库的身份验证

string commandText = "SELECT userdegre FROM Users WHERE username = @uname AND Password =@pwd";
using(MySqlCommand cmd = new MySqlCommand( commandText ,conn))
{                        
    cmd.Parameters.AddWithValue("@uname", myuser);
    cmd.Parameters.AddWithValue("@pwd", MypassMd5);
    var result = cmd.ExecuteScalar();
    if(result != null)
    {
          PublicVariables.UserId = myuser;
          PublicVariables.UserDegre = result.ToString();
    }
}

不要检查
读卡器.HasRows
。您需要调用
reader.Read()
,并检查结果

此外,还有一些附带问题:

  • MD5对于密码散列非常弱。真正地只是不要用它来做那件事。将bcrypt作为更好的选择。如果您根本不自己编写身份验证代码,那就更好了。找一个图书馆帮你把这些东西弄对。。。编写认证代码似乎很容易,通过了所有测试,但有一个微妙的缺陷,让你在几个月后被黑客攻击
  • 无需调用
    conn.Close()
    。这就是您的
    使用
    块的目的。他们会帮你处理的
  • 我也会去掉try/catch。因为您已经在向调用代码返回错误条件,所以我将把它作为处理错误的地方,这样您的try/catch应该处于该级别
  • 您正在搜索结果中不在选择列表中的
    userdegre
  • 参数化查询是您的朋友
  • 把这一切放在一起,你就会得到这样的结果:

    public static int checkuser(string myuser, string mypass)
    {
        string passHash = BCrypt(mypass); //Need to get bcyrpt library and make the function
        using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
        using (MySqlCommand cmd =
                     new MySqlCommand("SELECT username, password, userdegre FROM Users WHERE username = @user" ,conn))
        {
            cmd.Parameters.Add("@user", SqlDbType.NVarChar, 20).Value = myuser;
            conn.Open();
    
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (!reader.Read()) return 2;
                if (Convert.ToString(reader["password"]) != MypassMd5) return -1;
    
                PublicVariables.UserId = Convert.ToString(reader["username"]);
                PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
                return 1;
            }
        }
    }
    

    不要检查
    读卡器.HasRows
    。您需要调用
    reader.Read()
    ,并检查结果

    此外,还有一些附带问题:

  • MD5对于密码散列非常弱。真正地只是不要用它来做那件事。将bcrypt作为更好的选择。如果您根本不自己编写身份验证代码,那就更好了。找一个图书馆帮你把这些东西弄对。。。编写认证代码似乎很容易,通过了所有测试,但有一个微妙的缺陷,让你在几个月后被黑客攻击
  • 无需调用
    conn.Close()
    。这就是您的
    使用
    块的目的。他们会帮你处理的
  • 我也会去掉try/catch。因为您已经在向调用代码返回错误条件,所以我将把它作为处理错误的地方,这样您的try/catch应该处于该级别
  • 您正在搜索结果中不在选择列表中的
    userdegre
  • 参数化查询是您的朋友
  • 把这一切放在一起,你就会得到这样的结果:

    public static int checkuser(string myuser, string mypass)
    {
        string passHash = BCrypt(mypass); //Need to get bcyrpt library and make the function
        using (MySqlConnection conn = new MySqlConnection(PublicVariables.cs))
        using (MySqlCommand cmd =
                     new MySqlCommand("SELECT username, password, userdegre FROM Users WHERE username = @user" ,conn))
        {
            cmd.Parameters.Add("@user", SqlDbType.NVarChar, 20).Value = myuser;
            conn.Open();
    
            using (MySqlDataReader reader = cmd.ExecuteReader())
            {
                if (!reader.Read()) return 2;
                if (Convert.ToString(reader["password"]) != MypassMd5) return -1;
    
                PublicVariables.UserId = Convert.ToString(reader["username"]);
                PublicVariables.UserDegre = Convert.ToInt16(reader["userdegre"]);
                return 1;
            }
        }
    }
    
    最后,在@Joel和@Steve的帮助下,c#2008 net 3.5的工作副本如下:

    公共静态int usertrue(字符串myuser,字符串mypass)

    最后,在@Joel和@Steve的帮助下,c#2008 net 3.5的工作副本如下:

    公共静态int usertrue(字符串myuser,字符串mypass)


    请告诉我您使用的密码哈希比MD5更安全?MD5在这方面非常弱。@Joel,我将使用另一种加密来代替MD5,但由于我正在翻译一个用turbo pascal编写的旧程序,并且在我的旧程序中,我使用了这个,例如,但我认为使用shasum或Bcrypt,正如您所建议的,请告诉我您在密码哈希中使用的是比MD5更安全的东西?MD5在这方面非常弱。@Joel我将使用另一个加密来代替MD5,但当我翻译一个用turbo pascal编写的旧程序时,因为它在我的旧程序中,我使用了这个例子,但我认为使用shasum或Bcrypt是younew MySqlCommand建议的(“从username=@user的用户中选择username,password,userdegre”+”,conn))//这无法使用新的MySqlCommand(“从username=@user的用户中选择username、password、userdegre”