How to execute two separate queries from one DBCommand object? - mysql

I have the following code that tries to get records from two different tables and then add them to the particular comboboxes. Only the first query works and the second one is ignored.
Try
sqlConn = New MySqlConnection
connStr = New String("Server = localhost; Database = gen_database; Uid = root; Pwd =")
sqlConn.ConnectionString = connStr
myCommand = New MySqlCommand("Select DevCompanyName from developer_name_table; Select DevType from development_type_table")
myCommand.CommandType = CommandType.Text
myCommand.Connection = sqlConn
ComboBox1.Items.Clear()
sqlConn.Open()
MsgBox("Connection Open.")
dR = myCommand.ExecuteReader()
Do While dR.Read()
ComboBox1.Items.Add(dR("DevCompanyName"))
ComboBox2.Items.Add(dR("DevType")) 'Error shows here Could not find specified column in results: DevType
Loop
Catch ex As MySqlException
MsgBox(ex.ToString)
Finally
dR.Close()
sqlConn.Close()
End Try
I can think of another way which is to do it in multiple query but can the code be simplified to something like this?

Using a DBDataReader with 2 queries, only only the first executes because there is no way to signal which table/query each read item is from. Your "double read" loop seems to assume they will be returned at the same time (rather than one query after the other - the same way they are sent to the DBCOmmand); if it did work that way, it would fail whenever there are not the same number of rows in each table.
Using DataTables affords you the chance to simply bind the result to your combos rather than copying data into them:
Dim SQL = "SELECT * FROM Sample; SELECT * FROM Simple"
Dim ds As New DataSet
Using dbcon As New MySqlConnection(MySQLConnStr),
cmd As New MySqlCommand(SQL, dbcon)
dbcon.Open()
Dim da As New MySqlDataAdapter(cmd)
da.Fill(ds)
End Using
' debug results
Console.WriteLine(ds.Tables.Count)
Console.WriteLine(ds.Tables(0).Rows.Count)
Console.WriteLine(ds.Tables(1).Rows.Count)
If I look at the output window, it will print 2 (tables), 10000 (rows in T(0)) and 6 (rows in T(1)). Not all DBProviders have this capability. Access for instance will choke on the SQL string. Other changes to the way your code is composed:
DBConnections and DBCommand objects need to be disposed. They allocate resources, so they need to be created, used and disposed to release those resources.
The Using block does that for us: The target objects are created at the start and closed and disposed at End Using.
The code above stacks or combines 2 such blocks.
The code fills a DataSet from the query, in this case creating 2 tables. Rather than copying the data from one container to another (like a control), you can use a DataTable as the DataSource:
cboDevName.DataSource = ds.Tables(0)
cboDevName.DisplayMember = "DevName" ' column names
cboDevName.ValueMember = "Id"
cboDevType.DataSource = ds.Tables(1)
cboDevType.DisplayMember = "DevType"
cboDevType.ValueMember = "DevCode"
The result will be all the rows from each table appearing in the respective combo control. Typically with this type of thing, you would want the ID/PK and the name which is meaningful to the user in the query. The user sees the friendly name (DisplayMember), which the code can easily access the unique identifier for the selection (ValueMember).
When using bound list controls, rather than using SelectedIndex and the SelectedIndexChanged event, you'd use SelectedValue and SelectedItem to access the actual data.
MSDN: Using Statement (Visual Basic)

You can use .net connector (download here)
Then you can install it and add it to your project (project -> references -> add -> browse).
Finally add import:
Imports MySql.Data.MySqlClient
So you'll be able to use this:
Dim connStr as String = "Server = localhost; Database = gen_database; Uid = root; Pwd ="
Dim SqlStr as String = "Select DevCompanyName from developer_name_table; Select DevType from development_type_table"
Dim ds As DataSet = MySqlHelper.ExecuteDataset(CnStr, SqlStr)
ds will contain two datatables: one for each query

Related

Delete command using ID from DataGridView

I have data shown in DataGridView. I made a Button when selecting IDs in the grid the code below runs but I keep getting an error.
Dim cnx As New MySqlConnection("datasource=localhost;database=bdgeststock;username=root;password=")
Dim cmd As MySqlCommand = cnx.CreateCommand
Dim resultat As Integer
If ConnectionState.Open Then
cnx.Close()
End If
cnx.Open()
If grid.SelectedCells.Count = 0 Then
MessageBox.Show("please select the ids that u want to delete")
Else
cmd.CommandText = "delete from utilisateur where idu= #P1"
cmd.Parameters.AddWithValue("#P1", grid.SelectedCells)
resultat = cmd.ExecuteNonQuery
If (resultat = 0) Then
MessageBox.Show("error")
Else
MessageBox.Show("success")
End If
End If
cnx.Close()
cmd.Dispose()
How does this make sense?
cmd.Parameters.AddWithValue("#P1", grid.SelectedCells)
As you tagged this question WinForms, you are presumably using a DataGridView rather than a DataGrid (names matter so use the right ones). In that case, the SelectedCells property is type DataGridViewSelectedCellCollection. How does it make sense to set your parameter value to that? How is that going to get compared to an ID in the database?
If you expect to use the values in those cells then you have to actually get those values out. You also need to decide whether you're going to use a single value or multiple. You are using = in your SQL query so that means only a single value is supported. If you want to use multiple values then you would need to use IN and provide a list, but that also means using multiple parameters. I wrote an example of this type of thing using a ListBox some time ago. You can find that here. You could adapt that code to your scenario like so:
Dim connection As New SqlConnection("connection string here")
Dim command As New SqlCommand
Dim query As New StringBuilder("DELETE FROM utilisateur")
Select Case grid.SelectedCells.Count
Case 1
query.Append(" WHERE idu = #idu")
command.Parameters.AddWithValue("#idu", grid.SelectedCells(0).Value)
Case Is > 1
query.Append(" WHERE idu IN (")
Dim paramName As String
For index As Integer = 0 To grid.SelectedCells.Count - 1 Step 1
paramName = "#idu" & index
If index > 0 Then
query.Append(", ")
End If
query.Append(paramName)
command.Parameters.AddWithValue(paramName, grid.SelectedCells(index).Value)
Next index
query.Append(")")
End Select
command.CommandText = query.ToString()
command.Connection = connection
SelectedCells is a collection of cells
so it never can be only one id, so you have to guess which was you want or only allow one row to be selected
grid.SelectedCells(0).Value.ToString()
Or you have to program a loop to delete all selected rows

why does my datagridview not show any results?

I'm new to vb.net and am trying to display results from a mysql server in my datagridview. Can anyone maybe point out whats wrong with my code? Thanks in advance.
Leaving out my connection string for safety, but it does connect. And if I put a breakpoint in the code it does fill the dataset with the correct data
Dim con As New MySqlConnection("server=;user id=;password=;database=")
con.Open()
Dim adp As New MySqlDataAdapter("Select CONCAT(FirstName,' ',Surname) as Name, LeaveDaysAvailable as 'Leave Days Available' from leave_database.Employees;", con)
Dim ds As New DataSet()
adp.Fill(ds)
dgvMain.DataSource = ds
con.Close()
This is the result. No errors....
this is the result if i run the same query in mysql workbench
A DataSet doesn't contain data directly. It has a Tables collection that contains DataTable objects and each of those contains data. If you assign a DataSet to the DataSource property of your DataGridView, you need to also set the DataMember property to tell it which DataTable to get the data from.
The problem is, you haven't named your DataTable so you have nothing to assign to the DataMember. This line:
adp.Fill(ds)
actually creates a DataTable, populates it and adds it to the Tables collection. It has no name though, so you have no name to set the DataMember to. You would need to name the DataTable first, e.g.
adp.Fill(ds, "MyDataTable")
and then you can set the DataMember:
dgvMain.DataMember = "MyDataTable"
dgvMain.DataSource = ds
The alternative is to just bind the DataTable instead of the DataSet, in which case you don't need a name:
dgvMain.DataSource = ds.Tables(0)
The thing is though, why create a DataSet in the first place if you're just going to use one DataTable? Simply create a DataTable. You can then pass that DataTable to the Fill call and assign it to the DataSource property.
dataGridView1.AutoGenerateColumns = true;
Else You have to add columns to data grid you can do it using designer file or from code like
DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "First Name";
dataColumn.Binding = new Binding("Name");
dataGrid.Columns.Add(textColumn);
DataGridTextColumn textColumn = new DataGridTextColumn();
dataColumn.Header = "Leave day available";
dataColumn.Binding = new Binding("LeaveDaysAvailable");
dataGrid.Columns.Add(textColumn);
Using designer this will may help you https://msdn.microsoft.com/en-us/library/dyyesckz(v=vs.100).aspx

How to pass CommandText to another MySqlCommand?

The title is a bit furviant, I'll try to explain better. So in my application I've two connection string, one for the local database, and another for the web database. This two database must be updated with the same records. Now in my app when I add a record in the local database I execute a function that pass the MySqlCommand object to another function that use another connection string for the web database. In this second function I need to execute the same operation already performed in the local database. Example code:
Function local database
Dim query = "INSERT INTO text_app (name, last_name)
VALUES(#namep, #last_namep)"
Dim MySqlCommand = New MySqlCommand(query, dbCon)
MySqlCommand.Parameters.AddWithValue("#namep", name.Text)
MySqlCommand.Parameters.AddWithValue("#last_namep", last_name.Text)
MySqlCommand.ExecuteNonQuery()
Sync.SyncOut(MySqlCommand) 'Pass the object to another function
Function web database (SyncOut)
Using dbCon As MySqlConnection = establishWebConnection()
Try
dbCon.Open()
Dim MySqlCommand = New MySqlCommand(query_command, dbCon)
MySqlCommand.ExecuteNonQuery()
Return True
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Using
Now query_command contain the MySqlCommand passed from the local function, dbCon is the new connection object.
When I perform the .ExecuteNonQuery on the SyncOut function I get this error:
Invalid Cast from 'MySqlCommand' type to 'String' type.
What I need is take the .CommandText property contained in the query_command, but I can't access to this property.
What exactly am I doing wrong? How I can achieve this?
The first thing to do is change the name of the variable that represent the MySqlCommand. I can't find any plausible reason to allow a confusion as this to spread along your code. Do not name a variable with the same name of its class even if the language permits, it is very confusing
Dim query = "INSERT INTO text_app (name, last_name)
VALUES(#namep, #last_namep)"
Dim cmd = New MySqlCommand(query, dbCon)
and, of course, change every reference to the old name with the new one.
Now in the declaration of SyncOut write
Public Sub SyncOunt(ByVal cmd As MySqlCommand)
...
' Do not forget to open the connection '
dbCon.Open()
Dim aDifferentCommand = cmd.Clone()
aDifferentCommand.Connection = dbCon
....

Populating text boxes via Combobox and SQL database table

I am trying to populate a set of textboxes from a combobox on a form. The combo box is populated using a dataset when the form loads. When this is loaded it needs to show only one entry per unit number in the kitcombobox (which is a unit number for a kit with multiple pieces of equipment in it) but display the multiple pieces of equipment's information in the different text boxes when the unit number is selected via the kitcombobox. What approach should I take towards this? I'm really lost and this is all I have so far :(
Private Sub ckunit()
Dim ds As New DataSet
Dim cs As String = My.Settings.MacroQualityConnectionString
Dim kitcombobox As String = "SELECT DISTINCT Unit_Number, Status FROM Calibrated_Equipment WHERE CHARINDEX('CK', Unit_Number) > 0 AND Status='" & ckstatuscombbx.Text & "'"
Dim sqlconnect As New SqlConnection(cs)
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
sqlconnect.Open()
da.Fill(ds, "Calibrated_Equipment")
sqlconnect.Close()
kitcombbx.DataSource = ds.Tables(0)
End Sub
Assuming you are using WinForms, I think the key will be adding an event handler for the SelectionChangedCommitted event on kitcombbx.
You can then checked the properties on the combobox to check what is selected and run another query to pull equipment information for that kit. It'd probably look something like this:
Private Sub kitcombbx_SelectionChangeCommitted(sender As Object, e As EventArgs) _
Handles kitcombbx.SelectionChangeCommitted
Dim kit = kitcombbx.SelectedItem.ToString()
Dim kitEquipment = FetchKitEquipmentInformation(kit)
PopulateEquipmentInformation(kitEquipment)
End Sub
The way you're currently constructing your query (by concatenating string parameters directly from user input) results in bad performance for most database systems, and moreover, is a huge security vulnerability. Look up SQL injection for more detail (or read these two questions).
Better DB code would probably look something like this:
Dim query = New StringBuilder()
query.AppendLine("SELECT DISTINCT Unit_Number, Status ")
query.AppendLine("FROM Calibrated_Equipment ")
query.AppendLine("WHERE CHARINDEX('CK', Unit_Number) > 0 ")
query.AppendLine(" AND Status = #STATUS ")
Dim connection As New SqlConnection(My.Settings.MacroQualityConnectionString)
Dim command As New SqlCommand(query, connection);
command.Parameters.Add("#STATUS", ckstatuscombbx.Text);
Dim da As New SqlDataAdapter(kitcombobox, sqlconnect)
'And so on...
Your question is a bit broad (and therefore, likely off-topic for StackOverflow), see How to Ask.

How can I query by an value which is segmented, as 123-456-789 in mysql in vb.net?

My problem is, when I query by a usual ID, like number with no segments = 1234567890, it works nicely.
But I need to query by some kind of segmented values or ID as = 123-4567-890, when I try by 123-4567-890 this id it does not query anything in mysql although in the database this 123-4567-890 ID is present.
So what is the possible solution to search by segmented value in mysql in VB.NET
Here is below, my trying codes in vb
Public Sub student()
textbox1.text= "123-4567-890"
Try
dbConn()
Dim myAdapter As New MySqlDataAdapter("Select studentID, batchID, studentStatus from student where studentID= " & textbox1.text, ServerString)
Dim myDataTable As New DataTable
myAdapter.Fill(myDataTable)
If myDataTable.Rows.Count > 0 Then
vrSID = myDataTable.Rows(0).Item("studentID")
vrRecBatchID = myDataTable.Rows(0).Item("batchID")
vrAttendanceStatus = myDataTable.Rows(0).Item("studentStatus")
If vrSID = vrIDD Then
If vrAttendanceStatus = "Active" Then
Console.Beep()
batchRoutine()
Else
led3()
Console.Beep()
End If
End If
Else
Console.Beep()
teacher()
End If
Catch ex As Exception
Console.Beep()
MsgBox ("Error")
End Try
End Sub
When you are running into problems, the easiest way to solve them is to break things down to the simplest scenario. So instead of complicating things with table adapters and data tables, see what happens when you just send MySQL the query you 'think' works correctly.
So start out by seeing if you can get this to work, then go from there:
Dim sql As String = "select id from mytable where id = '123-4567-890'"
Using cnx As New MySqlConnection("connection_string")
Using cmd As New MySqlCommand(sql, cnx)
cnx.Open()
Using reader As MySqlDataReader = cmd.ExecuteReader()
Debug.Assert(reader.Read(), "No results")
Trace.WriteLine(reader.GetValue(reader.Item(0)))
End Using
End Using
End Using
if the column is in-fact a sort of student ID column (not social security I would expect), and the table has it without special characters, I would pre-strip the extra formatting (hyphens) from the string and pass the CLEANED value to the query as a parameter to get results.
Also, by explicitly adding the query string Plus the text box value, you are leaving yourself WIDE OPEN to sql injection. Look into Parameterized queries (my guess is it would be an object something like MySqlDataParameter data type.)