When you call ExecuteReader, it "locks" the connection because the reader fetches a row's worth of information only when you call Read. To free the lock, you close the connection. The best way to handle this is to always create a connection object in a
Using
block[
^], then inside that block you create a command in a second Using block, and a reader in a third inside that:
Using con As New SqlConnection(strConnect)
con.Open()
Using cmd As New SqlCommand("SELECT iD, description FROM myTable", con)
Using reader As SqlDataReader = cmd.ExecuteReader()
While reader.Read()
Dim myId As Integer = CInt(reader("iD"))
Dim myDesc As String = DirectCast(reader("description"), String)
Console.WriteLine("ID: {0}" & vbLf & " {1}", myId, myDesc)
End While
End Using
End Using
End Using
When your code exits the Using block by any means (Break, Return, or Exception for example) the object created within it is automatically closed and disposed for you and you never have a problem with unclosed readers or connections.