VB.Net Select-Like query in MS Access not working - vb.net

I need to show the data from the column 'Purchaser' starting with the text entered in the textbox 'Purchaser' on the form. I am using MS Access 2003 database.
For this I am using the following...
Dim query = "SELECT * FROM Details WHERE [Purchaser] LIKE '" & Purchaser.Text & "*'"
Dim dc = New OleDbCommand(query, cn)
Dim rows = dc.ExecuteNonQuery
cn.Close()
If rows = 0 Then
'Show a form for new entry
Else
Dim oleadap = New OleDbDataAdapter(query, cn)
Dim dset As DataSet = Nothing
oleadap.Fill(dset, "Details")
For i = 0 To rows
Dim purName = dset.Tables("Details").Rows(i).Item("Purchaser").ToString
Dim purAddr = dset.Tables("Details").Rows(i).Item("Address").ToString
'Populate a list
Next
End If
The variable 'rows' always turns out to be zero even if I check for a Purchaser starting with, say A, in the database.

That should be:
Dim query = "SELECT * FROM Details WHERE [Purchaser] LIKE '" _
& Purchaser.Text & "%'"
In MS Access, the wild card is asterisk (*), outside of it, the wildcard is percent (%)
In addition, you have ExecuteNonQuery, but that is not true. You are executing a query, here are a few notes for testing.
Dim query = "SELECT * FROM Details WHERE [Purchaser] LIKE '" _
& Purchaser.Text & "%'"
Dim dc = New OleDbCommand(query, cn)
Dim rows As OleDb.OleDbDataReader
rows = dc.ExecuteReader
If rows.HasRows Then
Do While rows.Read()
Console.WriteLine(rows("Purchaser"))
Loop
End If
Console.ReadLine()

Can you use % instead of *. And another one, use parameter.
Dim query = "SELECT * FROM Details WHERE [Purchaser] LIKE #purc & '%' "
Dim dc = New OleDbCommand(query, cn)
dc.Parameters.AddWithValue("#purc", Purchaser.Text)
Dim rows = dc.ExecuteNonQuery

Related

VB.Net - Write Records To Access Quickly

I have a large number of records to add to a Access database in realtime. The items are temperatures, water flows etc from electronic instruments.
The code I have is below, can it be improved or is there a different way to add records more quickly - currently, 10,000 records takes approx. 10secs.
I am currently simulating the data to prove the concept of adding large number of records.
Dim connetionString As String
Dim connection As OleDbConnection
Dim oledbAdapter As New OleDbDataAdapter
Dim sql As String
connetionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Neil Cooley\Desktop\Database1.accdb"
connection.Open()
Dim stop_watch_1 As New Stopwatch
Dim getDate As Date = Date.Now
For i As Integer = 1 To 10000 Step 1
sql = "INSERT INTO Lines VALUES('TAG " & i.ToString & "','" & i.ToString & "','192','" & getDate & "')"
oledbAdapter.InsertCommand = New OleDbCommand(sql, connection)
oledbAdapter.InsertCommand.ExecuteNonQuery()
Next
stop_watch_1.Stop()
MsgBox("Row(s) Inserted !! - " & stop_watch_1.ElapsedMilliseconds.ToString)
I think that the best you can hope for with that is to use SQL parameters, like this:
Dim connString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Users\Neil Cooley\Desktop\Database1.accdb"
Dim sql = "INSERT INTO Lines([tag], [num], [x], [dt]) VALUES(?, ?, '192', ?)"
Dim stop_watch_1 As New Stopwatch()
Using conn As New OleDbConnection(connString),
cmd As New OleDbCommand(sql, conn)
cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "#tag", .OleDbType = OleDbType.VarChar, .Size = 20})
cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "#num", .OleDbType = OleDbType.VarChar, .Size = 20})
cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "#date", .OleDbType = OleDbType.Date})
cmd.Parameters("#date").Value = DateTime.UtcNow()
conn.Open()
For i As Integer = 1 To 10000 Step 1
cmd.Parameters("#tag").Value = "TAG " & i.ToString()
cmd.Parameters("#num").Value = i.ToString()
cmd.ExecuteNonQuery()
Next
End Using
stop_watch_1.Stop()
MsgBox("Row(s) Inserted !! - " & stop_watch_1.ElapsedMilliseconds)
Make sure to set the data type and sizes of the parameters to match the database columns. You should declare the column names in the INSERT statement. The parameters are represented by ? in the query; they are added in the order they are used. The parameter names in the OleDbParameter instances are for convenience.
(Make sure to use a DateTime type in the database for DateTimes, and keeping it in UTC avoids daylight savings time change problems.)
Using a faster disk drive could help, perhaps one that the OS is not run from.
If using a different database is an option, perhaps a key-value store would serve you well. Or even just a plain CSV file.
I would try using a data table - it should run faster.
Say, try like this:
Dim sqlCon As New OleDbConnection(My.Settings.AccessDB)
Dim strSql As String = "SELECT * FROM tblBig WHERE ID = 0"
Dim cmdSQL As New OleDbCommand(strSQL, sqlCon)
Dim rstData = New DataTable
sqlCon.Open()
rstData.Load(cmdSQL.ExecuteReader)
Dim da As New OleDbDataAdapter(cmdSQL)
Dim daU As New OleDbCommandBuilder(da)
Dim stop_watch_1 As New Stopwatch
Dim getDate As Date = Date.Now
stop_watch_1.Start()
For i As Integer = 1 To 10000
Dim MyNewRow = rstData.NewRow
MyNewRow("City") = "City" & i
MyNewRow("FirstName") = "FirstName " & i
MyNewRow("LastName") = "LastName " & i
rstData.Rows.Add(MyNewRow)
If (i Mod 500) = 0 Then
'Debug.Print("data write" & stop_watch_1.ElapsedMilliseconds / 1000)
da.Update(rstData)
rstData.Clear()
End If
Next
' write data back to database
da.Update(rstData)
sqlCon.Close()
stop_watch_1.Stop()
MsgBox("Row(s) Inserted !! - " & stop_watch_1.ElapsedMilliseconds / 1000)
I have it set to write out in above every 500 rows.
However, you are getting about 1,000 rows per second, and I not at all sure you going to increase that rate - it is VERY good rates you already seeing, and I can't say the above is going to help much.
edit: I feel the need for speed!!! SUPER FAST!!!
Ok, if you want to bring this down from 10 seconds to 1/3 of a second?
by-pass the .net providers. Hit the database DIRECT with the native DAO object library. You get about 30 times faster.
So, try this:
Imports Microsoft.Office.Interop.Access
and then do this:
Dim dbE As New Dao.DBEngine
Dim db As Dao.Database
db = dbE.OpenDatabase("C:\test\test44.accdb")
Dim rstData As Dao.Recordset
rstData = db.OpenRecordset("tblBig")
Dim stop_watch_1 As New Stopwatch
stop_watch_1.Start()
For i As Integer = 1 To 10000
rstData.AddNew()
rstData("City").Value = "City" & i
rstData("FirstName").Value = "FirstName " & i
rstData("LastName").Value = "LastName " & i
rstData.Update()
Next
db.Close()
stop_watch_1.Stop()
MsgBox("Row(s) Inserted !! - " & stop_watch_1.ElapsedMilliseconds / 1000)
You find a min of 30x faster - even more. So, DIRECT use of the data engine, and by-passing all of the .net providers? You EASY insert 10,000 rows in WELL UNDER 1 second.

How to quick update MySQL table through a loop using VB.net

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

SQL query, field name paseed by reference vb.net

I'm having problems trying to make this work, I have this query on an application that Im writing in vb.net 2012:
Dim strSql As String = " SELECT * FROM Table_Master WHERE field & "'= ('" & txtCadena.Text & "')"
What I need is to have the option to choose the field that I'm querying writing the field name on a textbox.
Maybe something like:
strSql As String = string.format("SELECT * FROM Table_Master WHERE [{0}] = '{1}'", txtField.text, txtFieldValue.text.replace("'","''"))
This should work (only for text, not dates, numbers etc) but you have to know that it is not the best practice.
I finally made it doing this.
Dim Query As String
Dimm DT As DataTable = New DataTable
Query = "select Actual, Description, Unit_of_measurement from Table_ARTIClES WHERE NUMPART = '" & txtPartNum.Text & "'"
Dim Table As SqlDataAdapter = New SqlDataAdapter(Query, conn)
Table.Fill(DT)
lblInventory.Text = DT.Rows(0)("Actual").ToString

Data Grid View Filtering, Vb.net 2010 and Ms access

I have a problem on filtering my data on Data Grid View, whenever I search a the same data on my search box the, it continuously add the same data on my datagridview. How can I fix it?
I have two related table.
Here's my code:
Dim sqlqr As String
Dim sqlqry As String
Dim src As New BindingSource()
Dim tbl As DataTableCollection = ndst.Tables
sqlqry = "SELECT * FROM tblEmployeeInfo WHERE EmpIdNo='" & txtEmpid.Text & "'"
sqlqr = "SELECT * FROM tblAttendance WHERE EmpIdNo='" & txtEmpid.Text & "'"
If sqlqr <> sqlqry Then
cnn = New OleDbConnection(cs)
da = New OleDbDataAdapter(sqlqr, cnn)
cnn.Open()
da.Fill(ndst, "tblAttendance")
Dim vw As New DataView(tbl(0))
cnn.Close()
src.DataSource = vw
dgridDtr.DataSource = src
' dgridDtr.DataMember = "tblAttendance"
src.Filter = String.Format("[EmpIdNo] LIKE '%" & txtEmpid.Text & "%'")
dgridDtr.Refresh()
End If
here's the screenshot:
Heres The image Data Grid

Append Datatable in VB

I am developing windows app in vb where i want to append values in datatable withen a while loop as given below.
If hscode <> "" Then
da1 = New OleDbDataAdapter("select * from [" & tablename & "] where [ItemNo] like '" & hscode & "%'", myConnection)
da1.Fill(dt2)
dtab = dt2.Clone
dtab.Merge(dt2, True)
Dim l As Integer
l = 0
For l = 0 To dt2.Rows.Count - 1
dtab = dt2.Clone
dtab.ImportRow(dt2.Rows(l))
Next
dt2.Clear()
End If
In the above code when the datatable is populating for the first time its is taking only one row in DTAB datatable. and for the second time it is throwing an error.
Can anybody please tell me how to concatenate two datatable. actually i want to show multiple database values in one gridview depending upon some queries.
I can't see the rest of your code, but as it is now, there is no sense in filling a datatable (dt2), cloning its structure in another table (dtab) and then looping over dt2 rows and import these rows in dtab.
You could simply fill dtab
However, assuming that you need dtab separate from dt2 for other reasons, then I think you could remove practically all of your code if you use the Copy method of the DataTable
If hscode <> "" Then
da1 = New OleDbDataAdapter("select * from [" & tablename & "] where [ItemNo] like '" & hscode & "%'", myConnection)
da1.Fill(dt2)
dtab = dt2.Copy()
dt2.Clear()
End If
Also, I think also that you should change your original query to avoid string concatenation and use a parameterized query like this
....
Dim queryText = "select * from [" & tablename & "] where [ItemNo] like ?"
da1 = New OleDbDataAdapter(queryText, myConnection)
da1.SelectCommand.Parameters.AddWithValue("#p1", hscode & "%")
....
This will avoid problems with Sql Injection and parsing of the hscode value.