Populating text boxes via Combobox and SQL database table - mysql

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.

Related

How to execute two separate queries from one DBCommand object?

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

How do I loop Through Each Records in SQL server with Time Gap

I am making a CMS portal for my company which will fetch records from SQL server using ASP.NET:
My problem is that when I fetch values it only shows the last one. But my need is that it should display one by one values with say 5-10 seconds gap in between here is my code:
Imports System
Imports System.Data.Sql
Imports System.Data.SqlClient
Partial Class _Default
Inherits System.Web.UI.Page
Dim connectionString As String = "Data Source=soemserv;Initial Catalog=data;User Id=master; Password=hushotn;"
Dim conn As New SqlConnection(connectionString)
Public Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
conn.Open()
Dim comm As New SqlCommand("select Queue,[Timing(IST)],[Status at],TAT,[Staffing at] from DTD_LCD_Queue_Status", conn)
Dim reader As SqlDataReader = comm.ExecuteReader
While reader.Read()
lblQueueName.Text = reader("Queue").ToString.Trim
lblTimingIST.Text = reader("Timing(IST)").ToString.Trim
lblStatusAt.Text = reader("Status at").ToString.Trim
lblTAT.Text = reader("TAT").ToString.Trim
lblStaffingAt.Text = reader("Staffing at").ToString.Trim
End While
End Sub
End Class
How do I loop though each record I tried Do and Loop but its not working...
Thanks in advance!
EDIT
One Step Ahead with no LUCK!!!!
I have written this code but still getting the last row only
For I As Integer = 0 To 15
lblTemp.Text = I.ToString
Dim comm As New SqlCommand("select Queue,[Timing(IST)],[Status at],TAT,[Staffing at] from DTD_LCD_Queue_Status where SrNo='" + lblTemp.Text + "';", conn)
Dim reader As SqlDataReader = comm.ExecuteReader
While reader.Read()
lblQueueName.Text = reader("Queue").ToString.Trim
lblTimingIST.Text = reader("Timing(IST)").ToString.Trim
lblStatusAt.Text = reader("Status at").ToString.Trim
lblTAT.Text = reader("TAT").ToString.Trim
lblStaffingAt.Text = reader("Staffing at").ToString.Trim
Thread.Sleep(2000)
End While
Next
Note I have dynamically given rows i.e 0 to 15
Please guide me!!
Only the last values are printed because : you are fetching a group of rows(data) through the readr and in first iteration of the while loop the first rows(data) are copied to the controls then for the second iteration the contents in the controls are over written with the second row. This will happens in each iteration hence only the last data are displayed.
- This can be avoided by using
Group of controls which are dynamically created(but not practical and good)
using DataGridView(grid) to display the items How to do this
**The method you ware suggested (using Timer) is also possible but it is not a good programming practice only the last values ware displayed all the others flashed for a duration of 5-10 seconds **

Populate a textbox with mysql data after a combobox selection

So I have 2 mysql tables, one called "Service_Details" and one called "Payment_details"
I have a combobox in my form which displays the "service_id" field from the service table.
I'm trying to code a textbox, so when I select the service id from the combobox it writes the "service" which is another field in my service details table. The service id is linked to a service.
I am getting errors 'identifier expected' at [0] and 'Value of type 'system.data.datatablecollection' cannot be converted to 'string' at dss.tables
I can't seem to get it working after browsing the internet for an hour
Here is my code:
Private Sub cbxserviceid_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cbxserviceid.SelectedIndexChanged
Dim dss As New DataSet
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID='" + cbxserviceid.Text + "'", objconnection)
Dim cmddd = New MySqlCommandBuilder(daa)
daa.Fill(dss)
txtService1.Text = dss.Tables[0].Rows[0]["Service"].ToString();
End Sub
The indexes in VB.NET are expressed using the round braces, the square brackets are used in C#
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
Also avoid to use string concatenation for sql command texts, use always a parameterized query
Private Sub cbxserviceid_SelectedIndexChanged(......)
Dim dss As New DataSet
if cbxserviceid.SelectedIndex <> -1 Then
Dim daa As New MySqlDataAdapter("SELECT * from service_details WHERE ServiceID=#id", _
objconnection)
daa.SelectCommand.Parameters.AddWithValue("#id", Convert.ToInt32(cbxserviceid.Text))
daa.Fill(dss)
txtService1.Text = dss.Tables(0).Rows(0)("Service").ToString()
End If
End Sub
I have also removed the creation of the MySqlCommandBuilder, being the adapter a local variable it has no sense or effect (if this is all your code in this event of course).
Looking at the comments below and the chat with the poster there is also another error to fix.
When assign a DataSource, DisplayMember and ValueMember property of a combobox it is mandatory to follow a precise order to avoid unwanted side effects
cbxserviceid.DisplayMember = "ServiceID"
cbxserviceid.ValueMember = "ServiceID"
cbxserviceid.DataSource = datatable

remove redundant columns in selectable query datagridview

I have a single Datagridview on one of my windows forms that I intend to have the user select a query from a combo-box drop down menu, click a button, then the query results get displayed on the datagridview.
That is all working properly, however when a different query is selected and submitted, the datagridview displays additional empty columns used by the previously selected query.
What would be the best way to stop this from happening? is this based on the datagridview itself? or my subroutine to connect to the database and perform the query
I have tried clearing out the datatable(used in the query subroutine) and columns of the datagridview, but this has not solved the issue.
My various attempts at clearing the datagridview with a button (tried in various combinations):
Private Sub btnclearquery_Click(sender As System.Object, e As System.EventArgs) Handles btnclearquery.Click
mysql.qrydata.Clear()
DataGridViewqry.DataSource = Nothing
DataGridViewqry.Columns.Clear()
DataGridViewqry.Rows.Clear()
End Sub
My subroutine to perform the queries (referenced in another code file. sqlquery string is filled using select case when the user selects a query from the combo-box):
Public qrysqlconn As MySqlConnection
Public qrycommand As New MySqlCommand
Public qryadapter As New MySqlDataAdapter
Public qrydata As New DataTable
Public qrysql As String
Public Sub doquery(ByVal sqlquery As String)
qrysqlconn = New MySqlConnection
qrysqlconn.ConnectionString = "server=localhost;" _
& "user id=root;" _
& "password=W1nd0ws;" _
& "database=hystest"
qrysql = sqlquery
Try
qrysqlconn.Open()
qrydata.Clear()
qrycommand.Connection = qrysqlconn
qrycommand.CommandText = qrysql
qryadapter.SelectCommand = qrycommand
qryadapter.Fill(qrydata)
queries.DataGridViewqry.DataSource = qrydata
queries.DataGridViewqry.FirstDisplayedScrollingRowIndex = queries.DataGridViewqry.RowCount - 1
Catch myerror As MySqlException
MessageBox.Show("Database error: " & myerror.Message)
Finally
qrysqlconn.Close()
qrysqlconn.Dispose()
End Try
End Sub
I have had an issue like this before as well.
you may need to create a new instance of DataView for each new view you wish to display to get around this:
Dim dataview As DataView = _ds.YourStuff.DefaultView
dataview.Stuff
I managed to solve this, or at least create a work-around to the problem, by creating an individual subroutine/connection/datatable for each query. so instead of:
doquery(sql command)
I have used:
query1(<parameters>)
query2(<parameters>)
...
etc
This seems to work okay for now. this would imply that the issue was based on re-using the same datatable over and over again.

Visual Basic 2010 - Display multiple MySql queries to different datagridviews on a Form

Good day,
I'm developing a project where I use Visual Basic 2010 and MySql. The function of the project is to perform sports timing services. I'm semi-knowledgeable with programming in the above environments, and when I struggle, I Google for answers and it serves me well 99% of the time.
My problem is this: I have a database with tables for each sports event. All the data gets captured and all the functionality is working as intended. I would now like to display the results of this race on a Form using four GridViews (4 is the most race distances that are allowed). These results need to be separately displayed (using different queries) for each race distance (4 at most).
I have code to display the results, but this populates all four gridviews with the same data. Here is my code:
Private Sub ListResults()
Dim query As String = "SELECT RaceNo, FirstName, LastName, RaceDistance, RaceTime FROM " & frmMain.EventCode & _
" WHERE NOT ISNULL(RaceTime) AND RaceDistance = '" & frmMain.RaceDistance1 & "' ORDER BY RaceDistance ASC, RaceTime ASC;"
Dim connection As New MySqlConnection(frmMain.connStr)
Dim da As New MySqlDataAdapter(query, connection)
Dim ds As New DataSet
Try
If da.Fill(ds) Then
dgvLoadResultsA.DataSource = ds.Tables(0)
dgvLoadResultsB.DataSource = ds.Tables(0)
dgvLoadResultsC.DataSource = ds.Tables(0)
dgvLoadResultsD.DataSource = ds.Tables(0)
End If
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
da = Nothing
connection.Close()
connection = Nothing
End Try
End Sub
I understand that I need to produce four different queries (which I'm able to do), but I'm not sure how to send the results of those queries to the different gridviews. I don't seem to fully understand how to send the result of my queries to different tables in the dataset. I can just create the code by running the sub with different parameters and variables, but thought that there is a better way of doing this.
Any assistance in this matter would be highly appreciated.
Thank you in advance.
What you need to do is use a different DataSet per Query.
Personally I'd split your Query code into a separate Function taking the Event and Distance as Parameters and returning your DataTable;
Private Function GetResults(ByVal EventCode As Integer, ByVal RaceDistance As Integer) As DataTable
Dim query As String = "SELECT RaceNo, FirstName, LastName,
RaceDistance, RaceTime
FROM " & EventCode & _
" WHERE NOT ISNULL(RaceTime)
AND RaceDistance = '" & RaceDistance & "'
ORDER BY RaceDistance ASC, RaceTime ASC;"
Dim connection As New MySqlConnection(frmMain.connStr)
Dim da As New MySqlDataAdapter(query, connection)
Dim ds As New DataSet
Try
If da.Fill(ds) Then
Return ds.Tables(0)
End If
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
da = Nothing
connection.Close()
connection = Nothing
End Try
End Sub
I've assumed your Data Types here, you will of course need to modify this to use the correct Data Types.
Then you can attach your DataSources using;
dgvLoadResultsA.DataSource = GetResults(EventCodeA, RaceDistanceA)
dgvLoadResultsB.DataSource = GetResults(EventCodeB, RaceDistanceB)
dgvLoadResultsC.DataSource = GetResults(EventCodeC, RaceDistanceC)
dgvLoadResultsD.DataSource = GetResults(EventCodeD, RaceDistanceD)
Ideally you'd also pass in your Connection String to the GetResults Function, then your Function is Unit Testable, but I'll leave that decision to you.
Of course, you should ideally check that your Function returns a valid DataTable before attaching. But I didn't want to over complicate the solution!