MysqlDataReader.Read stuck on the last record and doesnt EOF - vb.net

i confused why mySqlDataReader.Read stuck on the last record and doesnt EOF ..
Here's my private function for executeSql :
Private Function executeSQL(ByVal str As String, ByVal connString As String, ByVal returnRecordSet As Boolean) As Object
Dim cmd As Object
Dim objConn As Object
Try
If dbType = 2 Then
cmd = New MySqlCommand
objConn = New MySqlConnection(connString)
Else
cmd = New OleDbCommand
objConn = New OleDbConnection(connString)
End If
'If objConn.State = ConnectionState.Open Then objConn.Close()
objConn.Open()
cmd.Connection = objConn
cmd.CommandType = CommandType.Text
cmd.CommandText = str
If returnRecordSet Then
executeSQL = cmd.ExecuteReader()
executeSQL.Read()
Else
cmd.ExecuteNonQuery()
executeSQL = Nothing
End If
Catch ex As Exception
MsgBox(Err.Description & " #ExecuteSQL", MsgBoxStyle.Critical, "ExecuteSQL")
End Try
End Function
And this is my sub to call it where the error occurs :
Using admsDB As MySqlConnection = New MySqlConnection("server=" & rs("server") & ";uid=" & rs("user") & ";password=" & rs("pwd") & ";port=" & rs("port") & ";database=adms_db;")
admsDB.Open()
connDef.Close()
rs.Close()
'get record on admsdb
Dim logDate As DateTime
Dim str As String
str = "select userid, checktime from adms_db.checkinout in_out where userid not in (select userid " &
"from adms_db.checkinout in_out join (select str_to_date(datetime,'%d/%m/%Y %H:%i:%s') tgl, fid from zsoft_bkd_padang.ta_log) ta " &
"on ta.fid=userid and tgl=checktime)"
Dim rsAdms As MySqlDataReader = executeSQL(str, admsDB.ConnectionString, True)
Dim i As Integer
'This is where the error is, datareader stuck on the last record and doesnt EOF
While rsAdms.HasRows
'i = i + 1
logDate = rsAdms(1)
'save to ta_log
str = "insert into ta_log (fid, Tanggal_Log, jam_Log, Datetime) values ('" & rsAdms(0) & "','" & Format(logDate.Date, "dd/MM/yyyy") & "', '" & logDate.ToString("hh:mm:ss") & "', '" & logDate & "')"
executeSQL(str, oConn.ConnectionString, False)
rsAdms.Read()
End While
'del record on admsdb
str = "truncate table checkinout"
executeSQL(str, admsDB.ConnectionString, False)
End Using
i'm new to vbnet and really have a little knowledge about it,, please help me,, and thank you in advance..

The issue is that you're using the HasRows property as your loop termination expression. The value of that property never changes. Either the reader has rows or it doesn't. It's not a check of whether it has rows left to read, so reading has no effect.
You are supposed to use the Read method as your flag. The data reader begins without a row loaded. Each time you call Read, it will load the next row and return True or, if there are no more rows to read, it returns False.
You normally only use HasRows if you want to do something special when the result set is empty, e.g.
If myDataReader.HasRows Then
'...
Else
MessageBox.Show("No matches found")
End If
If you don't want to treat an empty result set as a special case then simply call Read:
While myDataReader.Read()
Dim firstFieldValue = myDataReader(0)
'...
End While
Note that trying to access any data before calling Read will throw an exception.

Related

Visual basic - Incrementing the score

Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
Dim READER As MySqlDataReader
Dim Query As String
Dim connection As MySqlConnection
Dim COMMAND As MySqlCommand
Dim item As Object
Try
item = InputBox("What is the item?", "InputBox Test", "Type the item here.")
If item = "shoe" Then
Dim connStr As String = ""
Dim connection As New MySqlConnection(connStr)
connection.Open()
Query = "select * from table where username= '" & Login.txtusername.Text & " '"
COMMAND = New MySqlCommand(Query, connection)
READER = COMMAND.ExecuteReader
If (READER.Read() = True) Then
Query = "UPDATE table set noOfItems = noOfItems+1, week1 = 'found' where username= '" & Login.txtusername.Text & "'"
Dim noOfItems As Integer
Dim username As String
noOfItems = READER("noOfItems") + 1
username = READER("username")
MessageBox.Show(username & "- The number of items you now have is: " & noOfGeocaches)
End If
Else
MsgBox("Unlucky, Incorrect item. Please see hints. Your score still remains the same")
End If
Catch ex As Exception
MessageBox.Show("Error")
End Try
I finally got the message box to display! but now my code does not increment in the database, can anybody help me please :D
Thanks in advance
After fixing your typos (space after the login textbox and name of the field retrieved) you are still missing to execute the sql text that updates the database.
Your code could be simplified understanding that an UPDATE query has no effect if the WHERE condition doesn't find anything to update. Moreover keeping an MySqlDataReader open while you try to execute a MySqlCommand will trigger an error in MySql NET connector. (Not possible to use a connection in use by a datareader). We could try to execute both statements in a single call to ExecuteReader separating each command with a semicolon and, of course, using a parameter and not a string concatenation
' Prepare the string for both commands to execute
Query = "UPDATE table set noOfItems = noOfItems+1, " & _
"week1 = 'found' where username= #name; " & _
"SELECT noOfItems FROM table WHERE username = #name"
' You already know the username, don't you?
Dim username = Login.txtusername.Text
' Create the connection and the command inside a using block to
' facilitate closing and disposing of these objects.. exceptions included
Using connection = New MySqlConnection(connStr)
Using COMMAND = New MySqlCommand(Query, connection)
connection.Open()
' Set the parameter value required by both commands.
COMMAND.Parameters.Add("#name", MySqlDbType.VarChar).Value = username
' Again create the reader in a using block
Using READER = COMMAND.ExecuteReader
If READER.Read() Then
Dim noOfItems As Integer
noOfItems = READER("noOfItems")
MessageBox.Show(username & "- The number of items you now have is: " & noOfItems )
End If
End Using
End Using
End Using

Cannot open any more tables - OleDbException was unhandled

Good Day,
My question is how to handle the exception or get rid of the error pertaining to "Cannot open any more tables". For an overview to the program I was creating, I pull out the record of subject in ms access 2007, I loop to that record to randomly assign a schedule and one by one I insert the newly record with assigned schedule in the table.
My program flow of inserting the record work only for a certain number of times, like almost 200 and at some point it stop and pop-up the oledbexception
Thanks in advance for your time on answering my question.
here is my code for more detailed overview of my program,
Private Sub Assignsched(ByVal rType As String, ByVal subjectCode As String, ByVal SecID As String, ByVal CourseCode As String)
If shrdcon.con.State = ConnectionState.Closed Then
shrdcon.con.Open()
End If
Dim RoomNum As Integer
dtARoom.Clear()
Dim stoploop As Boolean
Dim count As Integer = 0
Dim rm1 As String
RoomAssign = ""
rm1 = "SELECT * FROM tblRoom WHERE RoomType = '" & rType & "'"
Dim dat As New OleDbDataAdapter(rm1, shrdcon.con)
dat.Fill(ds, "ARoom")
stoploop = False
count = 0
Do Until stoploop = "True"
RoomNum = rndm.Next(0, ds.Tables("ARoom").Rows.Count)
RoomAssign = ds.Tables("ARoom").Rows(RoomNum).Item(1)
ScheduleGeneration()
If checkExisting(sTime, eTime, RoomAssign, daypick) = False Then
RoomA = RoomAssign
GenerateOfferingID()
Dim cmd1 As New OleDbCommand()
cmd1.CommandText = "INSERT INTO [tblSubjectOffer]([SubjectOID],[SubjectCode],[SectionID],[Day],[sTime],[eTime],[RoomName],[CourseCode]) VALUES('" & _
myId & "','" & subjectCode & "','" & SecID & "','" & daypick & "'," & sTime & "," & eTime & ",'" & RoomA & "','" & CourseCode & "')"
cmd1.Connection = shrdcon.con
cmd1.ExecuteNonQuery()
cmd1.Dispose()
Dim pipz As New OleDbCommand("Update tblGenerator Set NextNo='" & myId & "' where TableName ='" & "tblSubjectOffer" & "'", shrdcon.con)
pipz.ExecuteNonQuery()
pipz.Dispose()
stoploop = True
Else
stoploop = False
End If
If stoploop = False Then
If count = 30 Then
stoploop = True
Else
count = count + 1
End If
End If
Loop
End Sub
This is typical error happens with Microsoft Jet engine when You have exceeded the maximum number of open TableIDs allowed by the Microsoft Jet database engine, which is 2048 with Jet3.5 engine and 1024 with older engines.
Even though you are closing the Command objects after each use, you are still using the same connection for the whole process, which actually holds the TableID's and is at some point of time exceeding the number of allowed open TableID's.
A probable solution would be to update the Jet Engine with the latest, which is available here
It might solve your problem, but if you are already using the latest engine, you have to look into other options to reduce the number of DB operations.
Try using the UpdateBatch method for applying the updates as a batch.
Hope this helps
Private Sub Command1_Click()
Dim myConnection As ADODB.Connection
Dim rsData As ADODB.Recordset
Set myConnection = New ADODB.Connection
myConnection.ConnectionString = "xxxxxxxxxxxxxxxxxxxx"
myConnection.Open
Set rsData = New ADODB.Recordset
rsData.CursorLocation = adUseClient
rsData.Open "select * from mytable", myConnection, adOpenStatic, adLockBatchOptimistic
For i = 1 To 10000
rsData.AddNew
rsData.Fields(0).Value = 1
rsData.Fields(1).Value = 2
Next i
rsData.UpdateBatch
rsData.Close
myConnection.Close
Set rsData = Nothing
End Sub
Good Evening,
Recently I encounter this type of error and i was able to resolve it by adding
con.close and call conState (a procedure conState- check below) before any insert/update or select statement
In my code i have something like
For i = 0 To DataGridView1.RowCount - 1
reg = DataGridView1.Rows(i).Cells(0).Value
Label2.Text = reg
'i added this two lines
***con.Close()***
***Call conState()***
Dim cmdcheck As New OleDbCommand("Select * from [2015/2016 UG CRF] where regno ='" & reg & "'", con)
Dim drcheck As OleDbDataReader
drcheck = cmdcheck.ExecuteReader
If drcheck.Read = True Then
GoTo A
End If
coursesFirst = String.Empty
coursesSecond = String.Empty
creditFirst = 0
creditSecond = 0
Dim cmdlevel As New OleDbCommand("Select * from [2015/2016 UG registration Biodata 5 april 16] where regno ='" & reg & "'", con)
Dim drlevel As OleDbDataReader
drlevel = cmdlevel.ExecuteReader
If drlevel.Read = True Then
level = drlevel.Item("level").ToString
faculty = drlevel.Item("faculty").ToString
program = drlevel.Item("programme").ToString
End If
...............
next
The conState is a connection testing if connection is closed is should open it again like in below
Public Sub conState()
If con.State = ConnectionState.Closed Then
con.Open()
End If
End Sub
This stop the error message
I got this exception in my C# application and the cause was using OleDbDataReader instances without closing them:
OleDbDataReader reader = cmd.ExecuteReader();
bool result = reader.Read();
reader.Close(); // <= Problem went away after adding this
return result;

Can't figure out what's wrong when trying to update a database entry

I can't figure out why updating my database entries wont work. Sometimes it tells me there is a syntax error, and other times when I try to delete an entry after trying an update it tells me that the connection was not closed. I'm not that familiar with SQL so any help would be appreciated.
Public Shared Property filename As String
Private dbConnection As New OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=IT_Checkout.accdb")
Private dbAdapter As OleDbDataAdapter
Private dbDataset As DataSet
Public Function deleteReport(ByVal rID As String,
ByRef msg As String) As Boolean
Dim sql As String
sql = "DELETE FROM Reports WHERE RID = '" & rID & "'"
If do_command(sql, msg) = False Then
Return False
End If
If File.Exists(My.Application.Info.DirectoryPath & "\reports\" & rID & ".dat") Then
My.Computer.FileSystem.DeleteFile(My.Application.Info.DirectoryPath & "\reports\" & rID & ".dat")
End If
Return True
End Function
Public Function updateReport(ByVal r As Report,
ByRef msg As String) As Boolean
Dim sql As String = "UPDATE Reports SET Name='" & r.name & "', Date='" & r.outDate & "', Notes='" & r.notes & "', Archived='" & r.archived.ToString & "' WHERE RID='" & r.getID & "'"
Return do_command(sql, msg)
End Function
Public Function do_command(ByVal sql As String,
ByRef msg As String) As Boolean
Dim command As OleDbCommand
Try
dbConnection.Open()
command = New OleDbCommand(sql, dbConnection)
command.ExecuteNonQuery()
dbConnection.Close()
Return True
Catch ex As Exception
msg = "From Command: " & ex.Message
Return False
End Try
End Function
If any of your values contain apostrophes your syntax will be wrong - you should use parameters instead of concatenating SQL:
Dim sql As String = "UPDATE Reports SET [Name]=?, [Date]=?, Notes=?, Archived=? WHERE RID=?"
command = New OleDbCommand(sql, dbConnection)
command.Parameters.Add("Name").Value = r.name
command.Parameters.Add("Date").Value = r.outDate
command.Parameters.Add("Notes").Value = r.notes
command.Parameters.Add("Archived").Value = r.archived
command.Parameters.Add("RID").Value = r.getID
command.ExecuteNonQuery()
dbConnection.Close()
You should also not share a single connection object - connections are pooled by .NET and are cheap to create.

Storing ID from SQL result

Im running the following code to tell if a user excists on a database - standard stuff. Obviously once the code is run a boolean true or false will be returned if there is a result. If a result is found i want to store the ID of the said result. Can anyone tell me how'd id go about doing this?
code:
Username = txtUserName.Text
Password = txtPassword.Text
dbConnInfo = "PROVIDER=Microsoft.Jet.OLEDB.4.0; Data Source = C:\Users\Dave\Documents\techs.mdb"
con.ConnectionString = dbConnInfo
con.Open()
Sql = "SELECT * FROM techs WHERE userName = '" & Username & "' AND '" & Password & "'"
LoginCommand = New OleDb.OleDbCommand(Sql, con)
CheckResults = LoginCommand.ExecuteReader
RowsFound = CheckResults.HasRows
con.Close()
If RowsFound = True Then
MsgBox("Details found")
TechScreen.Show()
Else
MsgBox("Incorrect details")
End If
There are a lot of problems with the code snippet you posted. Hopefully, I can help you correct these problems.
In order to load the ID of the result you'll want to use SqlCommand.ExecuteScalar() as this is optimized to pull back one result from Sql.
As to what is wrong with your code, you're wide open to Sql Injection attacks and you should be using Parametrized Queries as shown in my sample below.
Public Function AddProductCategory( _
ByVal newName As String, ByVal connString As String) As Integer
Dim newProdID As Int32 = 0
Dim sql As String = _
"INSERT INTO Production.ProductCategory (Name) VALUES (#Name); " _
& "SELECT CAST(scope_identity() AS int);"
Using conn As New SqlConnection(connString)
Dim cmd As New SqlCommand(sql, conn)
cmd.Parameters.Add("#Name", SqlDbType.VarChar)
cmd.Parameters("#Name").Value = newName
Try
conn.Open()
newProdID = Convert.ToInt32(cmd.ExecuteScalar())
Catch ex As Exception
Console.WriteLine(ex.Message)
End Try
End Using
Return newProdID
End Function
Source: MSDN

Data Reader formatting output

I'm using the following function to generate a list of users connected to a selected database. How would I change this to a single line for multiple identical results?
For example: "sa (3) - MYCOMPUTER" rather than listing "sa - MYCOMPUTER" three times?
Function ConnectedUsers(ByVal SelectedDatabase As String, ByVal SelectedInstance As String)
Dim myCommand As SqlCommand
Dim dr As SqlDataReader
Dim mystring As String = String.Empty
Try
Dim myConn As New SqlConnection(ConnectionString)
myConn.Open()
myCommand = New SqlCommand("select loginame,hostname from sysprocesses where db_name(dbid) = '" & SelectedDatabase & ";", myConn)
dr = myCommand.ExecuteReader()
While dr.Read()
mystring += GetFullName(dr(0).ToString().Trim()) & " - " & dr(1).Trim() & vbCrLf
End While
dr.Close()
myConn.Close()
Catch e As Exception
MessageBox.Show(e.Message)
End Try
Return mystring
End Function
Thanks.
The SQL Command should be
select loginame, count(*) as Nbr, hostname from sysprocesses where db_name(dbid) = '" & SelectedDatabase & "' group by loginame;"
and you should change the display to show the count (Nbr in this example) to be something like:
mystring += GetFullName(dr(0).ToString().Trim()) & "(" & dr(1).Trim() & ") - " & dr(2).Trim() & vbCrLf