ewask etyra
ewask etyra

Reputation: 23

How do I read HasRow then Update?

Is it possible to read HasRow and then Update ? This is the code what I have tried so far :

 If conn.State = ConnectionState.Closed Then
        conn.Open()
    End If

Dim sqlcmd As New MySqlCommand("SELECT * FROM tbl_online_attendance where employees_id = '" & lvRealAtt.Items(itms).SubItems(0).Text & "' and in_time = '" & lvRealAtt.Items(itms).SubItems(1).Text & "' ", conn)

            Dim dr As MySqlDataReader
            dr = sqlcmd.ExecuteReader
            If dr.HasRows Then
                Dim query As String

                query = "UPDATE tbl_online_attendance SET out_time = '" & lvRealAtt.Items(itms).SubItems(2).Text & "' where employees_id = '" & lvRealAtt.Items(itms).SubItems(0).Text & "' and in_time = '" & lvRealAtt.Items(itms).SubItems(1).Text & "'  "
                sqlcmd.Connection = conn
                sqlcmd.CommandText = query
                sqlcmd.ExecuteNonQuery() 'It error in this part
            Else

            End If

But it give's me error saying:

There is already an open DataReader associated with this Connection which must be closed first

Please avoid commenting Use Parameters Your code is Prone to SQL injection attack

Upvotes: 1

Views: 229

Answers (2)

Mary
Mary

Reputation: 15081

You should not have to check connection state if you keep your connections local to the method that they are used. Database objects like connections and commands need to be closed and disposed as soon as possible. Using...End Using blocks take care of this for you even if there is an error. Don't open a connection until directly before the .Execute....

Don't pull down data when you only need Count. .ExecuteScalar returns the first column of the first row of the result set, which in this case, is the Count. If you have a large table you need to look into If Exists which will stop as soon it finds a match whereas Count looks at the whole table.

Always use Parameters. Never concatenate strings to build sql queries to avoid sql injection. I had to guess at the datatypes of the parameters. Check your database to get the actual types and adjust the code accordingly.

Private Sub OPCode(ByVal itms As Integer)
    Dim RowCount As Integer
    Using conn As New MySqlConnection("Your connection string"),
        sqlcmd As New MySqlCommand("SELECT Count(*) FROM tbl_online_attendance where employees_id = @id and in_time = @inTime;", conn)
        sqlcmd.Parameters.Add("@id", MySqlDbType.Int32).Value = CInt(lvRealAtt.Items(itms).SubItems(0).Text)
        sqlcmd.Parameters.Add("@inTime", MySqlDbType.String).Value = lvRealAtt.Items(itms).SubItems(1).Text
        conn.Open()
        RowCount = CInt(sqlcmd.ExecuteScalar)
        If RowCount > 0 Then
            sqlcmd.CommandText = "UPDATE tbl_online_attendance SET out_time = @outTime where employees_id = @id and in_time = @inTime;"
            sqlcmd.Parameters.Add("@outTime", MySqlDbType.String).Value = lvRealAtt.Items(itms).SubItems(2).Text
            sqlcmd.ExecuteNonQuery()
        End If
    End Using
End Sub

Upvotes: 1

thatOneDude
thatOneDude

Reputation: 119

Every SqlDataReader needs to be closed before you could execute another query. so i suggest you to separate the sqlreader and the update query, put the reader into a boolean function to check either a row with those parameters exist or not.

Private Function HasRow(ByVal employeeid As Integer, ByVal date as DateTime) As Boolean
   HasRow = False
   Dim reader As SqlDataReader
   'do select query here
   'use the if reader.Read if you want to
   HasRow = reader.HasRows
   reader.Close()
End Function

Call the function before updating, if it's True then proceed the update. Let's say we put it into a Update Sub.

Private Sub Update()
    If HasRows(parameters here) Then
        'update query here
    End If
End Sub

Upvotes: 1

Related Questions