-1

OleDb in VB.net only returns the first column

I don't know where I've gone wrong, stared at it for 2 hours straight and tried 150 different variations. Don't know where the error is that makes it not return any other fields than the first one.

And yes, I know it looks really confusing, I was going to put the 5 readings as a function but I got overwhelmed by the problem

Private Sub StartBtn_Click(sender As Object, e As EventArgs) Handles StartBtn.Click
    Dim Numbers As New List(Of Integer)
    For X As Integer = 1 To 15
        Dim Num As Integer = RandomNum()
        Numbers.Add(Num)
    Next

    Dim temp_QuestionSet As New List(Of Question)

    provider = "Provider=Microsoft.ACE.OLEDB.12.0;"
    dataFile = "Data Source=C:\course work\dttmq.accdb"
    connString = provider & dataFile
    Try
        Connection.ConnectionString = connString
        Connection.Open()
    Catch ex As Exception
        System.Console.Beep()
        MsgBox("Error")
    End Try

    For Each Number In Numbers
        Dim _question As New Question

        _question.ID = Number

        Using Connection
            Dim command As New OleDbCommand("SELECT Question FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.Q = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using

        Using Connection
            Dim command As New OleDbCommand("SELECT (Answer1) FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.A = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using

        Using Connection
            Dim command As New OleDbCommand("SELECT Answer2 FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.B = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using

        Using Connection
            Dim command As New OleDbCommand("SELECT Answer3 FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.C = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using

        Using Connection
            Dim command As New OleDbCommand("SELECT Answer4 FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.D = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using

        Using Connection
            Dim command As New OleDbCommand("SELECT CorrectAnswer FROM final WHERE QuestionID = " & Number.ToString, Connection)
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    _question.Z = reader(0).ToString()
                End While
                reader.Close()
            Catch ex As Exception
            End Try
        End Using
        temp_QuestionSet.Add(_question)
    Next
End Sub
June7
  • 19,874
  • 8
  • 24
  • 34
  • 2
    Read https://stackoverflow.com/help/mcve, and then edit your question. – jarlh Jan 17 '18 at 14:17
  • 3
    What do you mean it "only returns the first column"? You're only selecting one column in the first place... Also, I don't think you understand what `Using Connection` is doing, may want to look closer into what that statement does and how it should be used...because right now, you're basically disposing it 6 times, which coincidentally closes it – soohoonigan Jan 17 '18 at 14:43
  • Your `SELECT` query retrieves only one column and you are reading it by `reader(0).ToString()` that's why you are getting the first column always, i don't see any problem here! – Md. Suman Kabir Jan 17 '18 at 14:46
  • `SELECT Question FROM` <--- you are only querying one column. Did you mean row? – braX Jan 17 '18 at 14:47
  • Currently you're running a query for each number in `Numbers` and each column separately, means 6*15=90 queries (!). While it could be done in one query like: `"SELECT Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer FROM final WHERE QuestionID IN (" & String.Join(",", Numbers) & ");"` - Also i guess that with the `RandomNum()`-method there could be duplicate numbers generated inside the for loop. – MatSnow Jan 17 '18 at 15:13
  • I think @soohoonigan answered it. You're using a Using which disposes your connection, thereby closing it. – dwilliss Jan 17 '18 at 16:02
  • This is an excellent situation for the debugger. Using it you could step thru the code and poll variables as it executes and learn why that code does what it does (and/or doesnt do). That in turn helps you write better code. The bare basic of **[step debugger](https://msdn.microsoft.com/en-us/library/y740d9d3.aspx)** could be learned in minutes - certain far less time than `2 hours straight` randomly trying 150 different things. – Ňɏssa Pøngjǣrdenlarp Jan 17 '18 at 16:20

1 Answers1

0

You have one connection outside of a loop, with several commands inside the loop. While this is leaning in the right direction, each of the commands is wrapped inside a Using block targeted on the connection object. This means you have disposed of your connection at the end of the very first command on the very first time through the loop, making the connection unusable.

While I'm here, you should also look at parameterized queries.

Put that all together, along with some other changes, and you end up with this:

Dim temp_QuestionSet As New List(Of Question)
Private Sub StartBtn_Click(sender As Object, e As EventArgs) Handles StartBtn.Click
    temp_QuestionSet.Clear()
    Dim QuestionSql As String = "SELECT Question, Answer1, Answer2, Answer3, Answer4, CorrectAnswer FROM final WHERE QuestionID = ?"

    provider = "Provider=Microsoft.ACE.OLEDB.12.0;"
    dataFile = "Data Source=C:\course work\dttmq.accdb"
    connString = provider & dataFile

    Using Connection As New OleDbConnection(connString), _
          command As New OleDbCommand(QuestionSql, Connection)

        command.Parameters.Add("ID", OleDbType.Integer)
        Connection.Open()

        For Each Number In Enumerable.Range(0,15).Select(Function(i) RandomNum())

            command.Parameters("ID").Value = Number
            Try
                Dim reader As OleDbDataReader = command.ExecuteReader()
                While reader.Read()
                    temp_QuestionSet.Add(New Question With {
                    .ID = Number,
                    .Q = reader("Question").ToString(),
                    .A = reader("Answer1").ToString(),
                    .B = reader("Answer2").ToString(),
                    .C = reader("Answer3").ToString(),
                    .D = reader("Answer4").ToString(),
                    .Z = reader("CorrectAnswer").ToString())
                End While
                reader.Close()
            Catch ex As Exception
               MsgBox("Error: " & ex.Message)
               Console.Beep()
            End Try
        Next

    End Using
End Sub

I'd also look at getting this down to ONE trip to your database to load all the questions in one go, and then shuffling the result. The code I provided should make it easy to go in that direction, where you can accomplish this just by changing the SQL command.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794