My code for updating mysql table having more than 2000 rows through a loop using VB.net is working fine but too slow. Is there any way to update it faster ? Anybody please help. Thanks. My code is given below.
Dim mysqlconn = New MySqlConnection
mysqlconn.ConnectionString = "server=localhost;user id=root;password=1234;database=Share"
mysqlconn.Open()
Dim adapter As New MySqlDataAdapter("SELECT * FROM name_list;", mysqlconn)
Dim datatable As New DataTable()
adapter.Fill(datatable)
Dim cmd As New MySqlCommand
cmd.Connection = mysqlconn
Dim sql As String
Dim i as integer = 0
While i <= datatable.Rows.Count - 1
Dim sy As String = datatable.Rows(i).Item(3).ToString.Trim
sql = "UPDATE Name_list Set Numerology = '" & "N-" & variable1 & " S- " & variable2 & "',FSTLetter = '" & variable3 & "',Timing = '" & vriable4 & "',P_Numerology = '" & variable5 & "' WHERE Symbol = '" & sy & "'"
sy = ""
cmd.CommandText = sql
cmd.ExecuteNonQuery()
i = i + 1
End While
adapter.Fill(datatable)
DataGridView1.DataSource = datatable
DataGridView1.Refresh()
Don't name variables the same as class names (DataTable, datatable) vb.net is case insensitive so it confuses intellisense.
Database connections and commands need to closed and disposed.
Using blocks do this for you even if there is an error.
You can set the connection string by passing it directly to the constructor of the connection. Likewise, you can set the command text and the connection by passing to the constructor of the command.
Don't open the connection until right before it is used. In this case we don't need a DataAdapter but if you are using one it is not necessary to open the connection at all. The .Fill method of the DataAdapter will open and close the connection. However if the DataAdapter finds an open connection it will leave it open.
To avoid confusion, I created 2 data tables. I used a single connection but I opened and closed it each time it is used. It is not disposed until the last End Using.
The first command retrieves only the sy column. Replace Column4_Name with the actual column name. We don't want to pull down data we don't need so no Select *.
Always use parameters to avoid sql injection which can damage your database. You need to check your database for the types of the fields. I had to guess. Each parameters value is set except sy which changes on each iteration.
No need to close the connection after the last Select command since the final End Using will close and dispose.
After the connection is closed we update the user interface.
Private Sub OPCode(variable1 As String, variable2 As String, variable3 As String, variable4 As String, variable5 As String)
Dim dtBeforeUpdate As New DataTable()
Dim dtAfterUpdate As New DataTable()
Using mysqlconn = New MySqlConnection("server=localhost;user id=root;password=1234;database=Share")
Using cmd As New MySqlCommand("SELECT Column4_Name FROM name_list;", mysqlconn)
mysqlconn.Open()
dtBeforeUpdate.Load(cmd.ExecuteReader)
mysqlconn.Close()
End Using
Using cmd As New MySqlCommand($"UPDATE Name_list Set Numerology = #Numerologh, FSTLetter = #FST, Timing = #Timing, P_Numerology = #P_Numerology WHERE Symbol = #sy ", mysqlconn)
cmd.Parameters.Add("#Numerology", MySqlDbType.String).Value = $"N-{variable1} S- {variable2}"
cmd.Parameters.Add("#FST", MySqlDbType.String).Value = variable3
cmd.Parameters.Add("#Timing", MySqlDbType.String).Value = variable4
cmd.Parameters.Add("#P_Numerology", MySqlDbType.String).Value = variable5
cmd.Parameters.Add("#sy", MySqlDbType.String)
mysqlconn.Open()
For Each row As DataRow In dtBeforeUpdate.Rows
cmd.Parameters("#sy").Value = row(0).ToString.Trim
cmd.ExecuteNonQuery()
Next
mysqlconn.Close()
End Using
Using cmd As New MySqlCommand("Select * From Name_list;", mysqlconn)
mysqlconn.Open()
dtAfterUpdate.Load(cmd.ExecuteReader)
End Using
End Using
DataGridView1.DataSource = dtAfterUpdate
End Sub
Actually, I don't get it. It seems like you are updated the entire table with the same data. Do you expect the variable1, variable2 etc. to change somehow?
Don't know where your variable1, variable2, etc come from, but those look to be static, so your loop is somewhat pointless it would seem. You're updating every row in the loop to the exact same values (unless there's other code you're not showing), so just update the table without the loop:
Using con As New MySQLConnection
con.ConnectionString = "server=localhost;user id=root;password=1234;database=Share"
con.Open
Using cmd As New MySQLCommand
cmd.Connection = con
cmd.CommandText = "UPDATE Name_list Set Numerology = '" & "N-" & variable1 & " S- " & variable2 & "',FSTLetter = '" & variable3 & "',Timing = '" & vriable4 & "',P_Numerology = '" & variable5 & "'"
cmd.ExecuteNonQuery
End Using
End Using
Related
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
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
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
no_hp = TextBox1.Text
alamat = TextBox2.Text
password = TextBox3.Text
cmd = New OleDbCommand("UPDATE [user] SET no_hp = '" & CInt(TextBox1.Text) & "',alamat = " & TextBox2.Text & ", pin ='" & CInt(TextBox3.Text) & "' WHERE id = " & id & "", conn)
cmd.Connection = conn
cmd.ExecuteReader()
i was trying to update my access database with the following error
i cant seem to see where i did wrong
i already changed the data type from the textbox to match with the data types used in the database
the no_hp and pin is integer so i converted it to Cint but it doesnt seem to work
i already tried to substitute it to a variable but still it didnt work
please tell me where i did wrong
Use Parameters to avoid SQL injection, a malious attack that can mean data loss. The parameter names in Access do not matter. It is the order that they are added which must match the order in the SQL statement that matters.
The Using...End Using statements ensure that you objects are closed and disposed even it there is an error. This is most important for connections.
You con't need to set the connection property of the command because you passed the connection in the constructor of the command.
ExcuteReader is for retrieving data. Use ExecuteNonQuery to update, insert of delete.
Private Sub UpdateUsers()
Using conn As New OleDbConnection("Your connection string")
Using cmd = New OleDbCommand("UPDATE [user] SET no_hp = ?,alamat = ?, pin =? WHERE id = ?", conn)
cmd.Parameters.Add("nohp", OleDbType.Integer).Value = CInt(TextBox1.Text)
cmd.Parameters.Add("alamat", OleDbType.VarChar).Value = TextBox2.Text
cmd.Parameters.Add("pword", OleDbType.Integer).Value = CInt(TextBox3.Text)
cmd.Parameters.Add("id", OleDbType.Integer).Value = id
conn.Open()
cmd.ExecuteNonQuery()
End Using
End Using
End Sub
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
Ok i have 2 queries that are running SQL Dependecy's to simulate the push - notifications
really my ownly question is why in heck my 2 pieces of code run so much differently ( slower / faster ) then the other
here is the fast code (milisecond updates)
lbnoes.Text = ""
'You must stop the dependency before starting a new one.
'You must start the dependency when creating a new one.
SqlDependency.Stop(getSQLString())
SqlDependency.Start(getSQLString())
Using cn As SqlConnection = New SqlConnection(getSQLString())
Using cmd As SqlCommand = cn.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT test1, test2 FROM dbo.[ztest]"
cmd.Notification = Nothing
' creates a new dependency for the SqlCommand
Dim dep As SqlDependency = New SqlDependency(cmd)
' creates an event handler for the notification of data changes in the database
AddHandler dep.OnChange, AddressOf dep_onchange1
cn.Open()
Using dr As SqlDataReader = cmd.ExecuteReader()
While dr.Read()
lbnoes.Text = lbnoes.Text & vbCrLf & (dr.GetString(0) & " " & dr.GetString(1))
'PopupNotifier1.ContentText = dr.GetString(0) & " " & dr.GetString(1)
'PopupNotifier1.Popup()
End While
End Using
End Using
End Using
HERE is the slow code (almost 2 minutes /update or so it seems) it is almost acting like its calling the on changes over and over. - hopefully you can tell me why cause i rather use this piece of code
lbnoes.Text = ""
Try
Dim con As New SqlConnection
Dim myConString As String = getSQLString()
Dim objcommand As SqlCommand = New SqlCommand
'con.ConnectionString = myConString
With objcommand
.Connection = con
Dim cmdText As String = "SELECT test1, test2 FROM ztest"
.CommandText = cmdText
End With
con.ConnectionString = myConString
SqlDependency.Stop(getSQLString())
SqlDependency.Start(getSQLString())
Dim dep1 As SqlDependency = New SqlDependency(objcommand)
AddHandler dep1.OnChange, AddressOf dep_onchange1
con.Open()
Using readerObj As SqlClient.SqlDataReader = objcommand.ExecuteReader
'This will loop through all returned records
While readerObj.Read
Dim t1 As String = readerObj("test1").ToString
Dim t2 As String = readerObj("test2").ToString
lbnoes.Text = lbnoes.Text & vbCrLf & (t1 & " " & t2)
' 'PopupNotifier1.ContentText = dr.GetString(0) & " " & dr.GetString(1)
' 'PopupNotifier1.Popup()
End While
End Using
con.Close()
Catch ex As Exception
End Try
Both on Changes are being invoked the same way ( different invoke methods / removehandles ) ...
Please help this confused nub.
Thanks in advance
Well, it's not easy to tell without going further in the application code, but it's much more efficient to access the datareader members trough index than trough column names.
Also, maybe the type conversion has something to do..
I would like to get the results of my reader to be able to be used in a WHERE clause in another SQL command. I have tried to put the reader into a variable to use but it does not work. I've never used readers before so I do not know how they work. Can anyone give me an idea of how to get the result of the reader into there where statement? Thanks.
The code:
Dim courseSelectCom = New SqlCommand("select stuff((select ','+course_name from course where school= '" & schoolSelect & "' for xml path ('')), 1, 1, '')", connection)
Dim reader = courseSelectCom.ExecuteReader()
If reader.Read() Then
Dim courseVar As String
courseVar = "%" & reader("course_name") & "%"
Using totalStudentCom = New SqlCommand("SELECT COUNT(student_ID) FROM student " & "course_name like #course", connection)
totalStudentCom.Parameters.AddWithValue("#course", courseVar)
Dim result = totalStudentCom.ExecuteScalar()
MessageBox.Show("Students for course = " & result.ToString)
End Using
End If
There are a couple of problems here.
First you should use parametrized query and not string concatenations for building sql commands
Second when a DataReader is opened, the connection object cannot serve another command unless you have specified the substring MultipleActiveResultSets=True; in your connection string
Dim courseSelectCom = New SqlCommand("select course_name from course where school= #school", connection)
courseSelectCom.Parameters.AddWithValue("#school", schoolSelect)
Dim reader = courseSelectCom.ExecuteReader()
if reader.Read() then
Dim courseVar As String
courseVar = "%" & reader("course_name") & "%"
Using totalStudentCom = new SqlCommand("SELECT COUNT(student_ID) FROM student " & _
"course_name like #course", connection)
totalStudentCom.Parameters.AddWithValue("#course", courseVar)
Dim result = totalStudentCom.ExecuteScalar()
MessageBox.Show("Students for course = " & result.ToString)
End Using
End If
Remember that this works only if MARS is enabled