Не удалось прочитать, когда данных нет

У меня есть этот код, его работа (вид).

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

im получить ошибку с этой строкой:

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

почему в нем говорится «нет данных»,

У меня есть все данные в базе данных?

может кто-нибудь помочь мне исправить этот код? благодарю вас ..

Всего 2 ответа


Вы не должны использовать цикл вообще. Не должно быть никакого способа, чтобы вы могли получить более одной записи, чтобы использовать цикл? Вы должны использовать оператор 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

Если возможно иметь две записи с одним и тем же именем пользователя, то что-то не так с дизайном базы данных и вашим приложением. Этот столбец должен быть уникальным, и ваше приложение должно тестировать существующую запись, когда кто-то пытается зарегистрироваться.


SqlDataReader является элементом чтения только для чтения. Ошибка возникает, потому что вы дважды вызываете функцию READ читателя; один раз, как true для увеличения до 1, и второй раз, чтобы получить ложь, чтобы выпасть из инструкции 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 - ваш друг. Изучите их. Это единственный простой способ борьбы с SQL Injection при использовании классов SqlClient.

Во-вторых, обратите внимание, что я делаю фактическое извлечение данных из читателя внутри цикла WHILE. Это гарантирует, что для меня есть фактические данные.

В-третьих, обратите внимание на инструкции USING для объектов SqlConnection и SqlCommand. Это помогает в сборе мусора, а также имеет несколько других преимуществ.

Наконец, обратите внимание на проверки, которые я делаю на SqlDataReader, прежде чем пытаюсь получить к нему доступ. Такие вещи предотвратят появление другой ошибки, если вы не вернете никаких результатов.


Есть идеи?

10000