Viren Sareen
Viren Sareen

Reputation: 74

Invalid attempt to read when reader is closed Error

I am stumped with this problem, my database is local host and every other form I have no issues with but here, when I click the update button, I get this error which is very frustrating as I am very sure the SQL connection should be open! My code for the button is given.

Error: 'Invalid attempt to read when reader is closed'

Private Sub UpdateButton_Click(sender As Object, e As EventArgs) Handles UpdateButton.Click

    MysqlConn = New MySqlConnection
    MysqlConn.ConnectionString = "server=localhost;userid=root;password=alpine;database=database1"
    Dim Reader As MySqlDataReader

    Dim vals(2, 2) As Decimal
    vals(0, 2) = Convert.ToDecimal(Cbudget.Text.ToString - OutBox.Text.ToString + InBox.Text.ToString)
    vals(1, 0) = Convert.ToDecimal(Newfigbox.Text.ToString)
    vals(2, 0) = Convert.ToDecimal(OutBox.Text.ToString - InBox.Text.ToString)
    vals(1, 1) = Convert.ToDecimal(FigureBox.Text.ToString + Newfigbox.Text.ToString)

    Try
        MysqlConn.Open()
        Dim Query As String
        Query = "UPDATE accounts SET Current_Budget='" & vals(1, 0) & "';"
        Command = New MySqlCommand(Query, MysqlConn)
        Reader = Command.ExecuteReader
        MysqlConn.Close()
    Catch ex As MySqlException
        MessageBox.Show(ex.Message)
        MysqlConn.Close()
    End Try

    Try
        MysqlConn.Open()
        Dim Query As String
        Query = "UPDATE stocktable, clientdetails SET stocktable.Quantity='" & vals(1, 1) & "', clientdetails.Balance='" & vals(2, 0) & "' WHERE 'stocktable.Type_Of_Metal' ='" & ComboBox1.Text & "' AND 'clientdetails.Name' ='" & ClientBox.Text & "';"
        Command = New MySqlCommand(Query, MysqlConn)
        Reader = Command.ExecuteReader
        MysqlConn.Close()
    Catch ex As MySqlException
        MessageBox.Show(ex.Message)
        MysqlConn.Close()
    End Try
    Cbudget.Text = Nothing
    Try
        MysqlConn.Open()
        Dim Query As String
        Query = "SELECT Current_Budget FROM accounts"
        Command = New MySqlCommand(Query, MysqlConn)
        Reader = Command.ExecuteReader
        MysqlConn.Close()
        While Reader.Read
            vals(0, 1) = Reader.GetDecimal("Current_Budget")
            Cbudget.Text = vals(0, 1)
        End While
        MysqlConn.Close()
    Catch ex As MySqlException
        MessageBox.Show(ex.Message)
        MysqlConn.Close()
    End Try

End Sub'

Upvotes: 0

Views: 786

Answers (1)

Steve
Steve

Reputation: 216303

Probably your problem is just a copy/paste error. It seems that before executing the reader for the last SELECT command you close the connection. (As you do in your previous two UPDATE commands) This effectively is the reason of your error message.
But a part from this you have other problems in your code.

First. you should send your UPDATE using ExecuteNonQuery. The ExecuteReader is used when you want to read back something from your database via a SELECT query. It works also for UPDATE/INSERT/DELETE etc but the infrastructure created for reading is not needed and thus is a useless consumption of resources.

Second. You could send two (or more) commands using a single commandtext. Just separe the two commands with a semicolon and execute the commandtext via ExecuteNonQuery

Third. You should always use a parameterized query to avoid Sql Injection and problem with parsing your values. For example a decimal contains the decimal separator that in your locale is expressed via a particular symbol, but in other locales is different, and thus your queries stop to work. (The same problem happens also with normal strings that contain a single quote). The parameter approach will remove both of these problems.

Finally. All disposable objects like Connections, Commands and Readers should be disposed when you finish to use them. The Using Statement ensures this correct behavior (And If you wonder about the closing of the connection, the End Using also close the connection)

Dim vals(2, 2) As Decimal
vals(0, 2) = Convert.ToDecimal(Cbudget.Text.ToString - OutBox.Text.ToString + InBox.Text.ToString)
vals(1, 0) = Convert.ToDecimal(Newfigbox.Text.ToString)
vals(2, 0) = Convert.ToDecimal(OutBox.Text.ToString - InBox.Text.ToString)
vals(1, 1) = Convert.ToDecimal(FigureBox.Text.ToString + Newfigbox.Text.ToString)

Query = "UPDATE accounts SET Current_Budget=@budget; " & _
        "UPDATE stocktable, clientdetails " & _
        "SET stocktable.Quantity=@qty, " & _
        "clientdetails.Balance=@bal " & _ 
        "WHERE `stocktable`.`Type_Of_Metal` = @type " & _
        "AND `clientdetails`.`Name` = @client;"
Try
    Using MysqlConn = New MySqlConnection(...constring here...)
    Using Command = New MySqlCommand(Query, MysqlConn)
        command.Parameters.AddWithValue("@budget", vals(1, 0))
        command.Parameters.AddWithValue("@qty", vals(1, 1))
        command.Parameters.AddWithValue("@bal", vals(2, 0))
        command.Parameters.AddWithValue("@type", ComboBox1.Text)
        command.Parameters.AddWithValue("@client", ClientBox.Text)
        command.ExecuteNonQuery()

        Command.CommandText = "SELECT Current_Budget FROM accounts"
        Command.Parameters.Clear()        
        Using Reader = Command.ExecuteReader()
            While Reader.Read
                vals(0, 1) = Reader.GetDecimal("Current_Budget")
                Cbudget.Text = vals(0, 1)
            End While
        End Using
    End Using
Catch ex As MySqlException
    MessageBox.Show(ex.Message)
End Try

Upvotes: 2

Related Questions