【问题标题】:Failed to read when no data is present没有数据时读取失败
【发布时间】:2018-10-21 04:33:14
【问题描述】:

我有这个代码,它的工作(有点)。

Dim connString As String = ConfigurationManager.ConnectionStrings("connectionstring").ConnectionString
    Dim conn As New SqlConnection(connString)
    conn.Open()
    Dim comm As New SqlCommand("SELECT username, Password,type   FROM users WHERE username='" & TextBox1.Text & "' AND Password='" & TextBox2.Text & "'", conn)
    Dim reader As SqlDataReader
    reader = comm.ExecuteReader

    Dim count As Integer
    count = 0
    While reader.Read
        count = count + 1
    End While
    If count = 1 Then
        MessageBox.Show("username and password are correct")


        Form2.Show()


        Form2.Label1.Text = Me.TextBox1.Text
        Form2.Label2.Text = reader(2).ToString
    ElseIf count > 1 Then
            MessageBox.Show("username and password are duplicated")
        Else
            MessageBox.Show("username and password are wrong")

    End If

这行出错了:

Form2.Label2.Text = reader(2).ToString
and error is "Invalid attempt to read when no data is present"

为什么它说“没有数据”

我有数据库中的所有数据?

有人可以帮我更正这段代码吗? 谢谢你..

【问题讨论】:

  • 您的 While 循环将继续,直到 reader.Read 返回 False 表示没有更多数据。您已到达数据末尾,无法访问 reader(2)。如果要获取类型,请在第一个 reader.Read 之后立即执行。
  • 您不应在 SQL 查询中连接字符串。使用参数来防止 SQL 注入。此外,您永远不应该将密码存储为纯文本。

标签: vb.net sqldatareader


【解决方案1】:

您根本不应该使用循环。应该不可能获得多个记录,那么循环有什么用呢?您应该使用If 语句,仅此而已:

If reader.Read() Then
    'There was a match and you can get the data from reader here.
Else
    'There was no match.
End If

如果可能有两条记录具有相同的用户名,那么您的数据库设计和应用程序就有问题。该列应该是唯一的,并且当有人尝试注册时,您的应用应该测试现有记录。

【讨论】:

    【解决方案2】:

    SqlDataReader 是一个只进数据读取元素。发生错误是因为您两次调用阅读器的 READ 函数;一次为 true 以递增到 1,第二次为 false 以退出 while 语句。由于您不再处于 WHILE 语句中,因此读者必须已阅读结果集的末尾,因此没有数据可供您阅读。

    考虑下面的更改代码:

    Dim connString As String = ConfigurationManager.ConnectionStrings("connectionstring").ConnectionString
    Dim count As Integer = 0 
    Dim userType as string = ""
    
    Using conn As New SqlConnection(connString)
        conn.Open()
        Using Comm as SqlCommand = conn.CreateCommand 
           comm.commandText = "SELECT username, Password, type FROM Users WHERE username = @UserName AND Password = @Pwd; "
           comm.parameters.AddWithValue("@Username", TextBox1.Text) 
           comm.parameters.AddWithValue("@Password", Textbox2.text) 
    
           Dim reader As SqlDataReader
           reader = comm.ExecuteReader
    
           If reader IsNot Nothing Then 
              If reader.HasRows() Then 
                 While reader.read 
                    count = count + 1 
                    If Not reader.IsDbNull(2) Then userType = reader(2).ToString 
                 End While 
              End If 
              If Not reader.IsClosed Then reader.close
              reader = Nothing 
           End If 
        End Using 
    End Using
    If count = 1 Then
        MessageBox.Show("username and password are correct")
        Form2.Show()
    
        Form2.Label1.Text = Me.TextBox1.Text
        Form2.Label2.Text = userType 
     ElseIf count > 1 Then
        MessageBox.Show("username and password are duplicated")
     Else
        MessageBox.Show("username and password are wrong")
     End If
    

    首先,SQLParameters 是你的朋友。学习它们。在使用 SqlClient 类时,它们是对抗 SQL 注入的最简单方法。

    其次,请注意,我正在 WHILE 循环内从阅读器中实际检索数据。这确保有实际数据供我阅读。

    第三,注意 SqlConnection 和 SqlCommand 对象上的 USING 语句。这有助于垃圾收集,并且还有其他一些好处。

    最后,请注意我在尝试访问之前对 SqlDataReader 所做的检查。如果您没有返回任何结果,这样的事情将防止出现另一个错误。

    【讨论】:

    • 感谢您的回答。我只想问。cn.CreateCommand 是什么?因为我在那里出错了
    • 对不起,我总是使用 cn 作为连接对象,并输入了它而不是 Conn
    • AddWithValue,不要使用它,使用Add 并指定数据类型和长度。不这样做时,它会推断类型并且可能不是您想要的......还有一些保留关键字在该选择语句中,它们应该被括在括号[ ]只是MHO...
    • @StephenWrighton If reader IsNot Nothing Then 不是必需的。 reader = comm.ExecuteReader 无论是否有行都返回一个阅读器。如果命令有问题,它会在到达 If 语句之前爆炸。
    • @StephenWrighton ` If reader.HasRows() Then ` 是不必要的。如果没有行,While reader.read 将立即返回 False,
    猜你喜欢
    • 2011-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 2014-10-29
    • 2020-06-15
    相关资源
    最近更新 更多