【问题标题】:SqlDataReader reads every other row?SqlDataReader 每隔一行读取一次?
【发布时间】:2014-08-28 04:00:51
【问题描述】:

我尝试了几个小时检查我的代码,试图找出哪里出错了,而谷歌似乎也没有答案。 基本上我正在运行这段代码:

public bool LoginRequest(string ReceivedUsername, string ReceivedPassword)
    {

        bool ValidLogin = false;

        try
        {

            using (SqlConnection myConnection = new SqlConnection(ConnectString))
            {
                myConnection.Open();
                Log.Debug("Succesful sql connection");
                SqlCommand userSELECTcom = new SqlCommand("SELECT username,password FROM users;", myConnection);
                SqlDataReader reader = userSELECTcom.ExecuteReader();

                    //verify login
                    while (reader.Read())
                    {
                        CompareUsername = reader["username"].ToString();
                        ComparePassword = reader["password"].ToString();
                        Log.Debug(ReceivedUsername + " against " + CompareUsername);
                        Log.Debug(ReceivedPassword + " against " + ComparePassword);

                        if (CompareUsername == ReceivedUsername && ComparePassword == ReceivedPassword)
                        {
                            ValidLogin = true;
                            Log.Debug(ReceivedUsername + " has logged in successfully!!!");
                            myConnection.Close();//close sql conn
                            reader.Close();//close sqldatareader
                            return ValidLogin;
                        }

                        else if (CompareUsername != ReceivedUsername || ComparePassword != ReceivedPassword)
                        {
                            if (!reader.Read())
                            {
                                Log.Debug(ReceivedUsername + " has not logged in successfully with password: " + ReceivedPassword);
                                myConnection.Close();//close sql conn
                                reader.Close();//close sql data reader
                                return ValidLogin;
                            }
                        }
                    }
                    //end of verify sequence
            }

        }
        //logging any login request issues
        catch (Exception e)
        {
            Log.Debug(e);
        }
        return ValidLogin;

    }

我设置了一个日志记录程序,它可以告诉我代码执行时发生的所有事情。这些行:" Log.Debug(ReceivedUsername + " 与 " + CompareUsername); Log.Debug(ReceivedPassword + " 对 " + ComparePassword); "

帮助我查看阅读器正在检查哪一行。我尝试了六行,每行都有唯一的用户名和密码,结果基本上表明只有第 1、3 和 5 行由读者根据用户的输入进行检查。因此,如果我尝试使用第 2 行、第 4 行或第 6 行中的用户名和密码登录我的客户端,我会收到一条错误消息,提示我登录失败。谁能解释为什么会这样?

【问题讨论】:

  • 只是给你一个旁注。如果您在连接周围使用“使用”关键字,则无需致电。关闭它。它继承了 IDisposable,它使用你的调用。
  • 通常最好直接从数据库查询而不是从表中检索所有数据。推荐使用where子句。
  • 肯定会考虑到 Cubicle.Jockey。你能进一步解释一下哈桑吗?
  • @Jaja。是的。我要求将where clause 添加到您的 sql 查询中。
  • @HassanNisar 不太了解这个条款,所以我对它进行了一些研究。我可能错了,但这种说法不会让你容易受到 SQL 注入攻击吗? SELECT username FROM users WHERE username = 'var_user_input'

标签: c# sql sql-server-2012-express


【解决方案1】:

在您当时没有找到登录信息的情况下,您有一个额外的Reader.Read() 呼叫。这是跳到下一条记录,然后你的主循环的Reader.Read() 转到下一条。

不过,您不需要像这样循环。构建一个按用户名查找记录的查询。如果没有记录,登录失败。如果有,请检查密码。

【讨论】:

  • 啊啊啊我明白了....有道理。但是在我尝试代码之前,如何检查阅读器是否还有没有条件的行!Reader.read()?
  • 可以使用Reader.HasRows。
【解决方案2】:

while 块内的 if 语句中有第二个 reader.Read()。这会导致您的代码跳过记录。

【讨论】:

    【解决方案3】:

    为了简单起见,您可以直接从数据库中查询。

    以下是检查接收到的用户名和密码是否存在于数据库中的示例代码:

    string sql = @"SELECT username,password FROM users 
                 WHERE username=@username and password = @password";
    
    SqlCommand userSELECTcom = new SqlCommand(sql, myConnection);
    userSELECTcom.Parameters.AddWithValue(@username, ReceivedUsername);
    userSELECTcom.Parameters.AddWithValue(@password, ReceivedPassword);
    
    using(SqlDataReader reader = userSELECTcom.ExecuteReader())
    {
       ValidLogin = reader.HasRows; 
    }
    

    【讨论】:

    • 非常感谢...比我使用的代码短得多!我马上修改我的代码。
    • @Jaja。请注意。你可以避免声明bool ValidLogin。您可以直接使用return reader.HasRows;。此外,当您对SqlConnection 使用using 语句时,您不必关闭连接,您可以跳过myConnection.Close()
    • 是的,我删除了所有不需要的 connection.Close() 语句。我想知道现在是否要在我的 catch 语句中返回 false ?
    • 你可以在 catch 块中 return false。您也可以在 Log 中写入条目。
    • 谢谢...还有最后一个问题:在 if 条件语句中使用函数之前,最好将函数的返回值分配给布尔值,还是应该只在 if 括号内调用函数?
    【解决方案4】:
    else if (CompareUsername != ReceivedUsername || ComparePassword != ReceivedPassword)
    {
    if (!reader.Read())  //remove this condition it will skip the current loop                             
    {
    Log.Debug(ReceivedUsername + " has not logged in successfully with password: " + ReceivedPassword);
    myConnection.Close();//close sql conn
    reader.Close();//close sql data reader
    return ValidLogin;
    }
    }
    

    【讨论】:

    • 你能正确缩进你的答案吗?看起来很奇怪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    相关资源
    最近更新 更多