How to retrieve several rows from database - mysql

Okay, so I've made a new project which allows users to send messages to each other. I've almost got it finished, just a few things need to be cleared up.
I've successfully allowed the user to send the message (via mysql). Now Im at the part where Im supposed to retrieve the message and display it in the form; this is where Im stuck. It'd be easy to do if the user has only 1 message in the database, but what if he had more than 1? How would I retrieve them all and display them in the form. Im using this query:
SELECT ToID
FROM Message
WHERE (ID LIKE #ID)
What it does is check the database for any messages containing the recipient as the user's ID. If the database does in fact contain any message, then the program will display them in the textboxes. But in the case if more than 1 message, how would the database display them in the form? The form has textboxes for:
Sender
Subject
Date.
This is the query I hoped to use for retrieving the message:
SELECT ID, Title, Body, Date, FromUsername
FROM Message
WHERE (ID LIKE #ID)
Please help? Any other solutions are fine as long as its easy to understand(im new to vb).

If I understand you correctly, why not use a list box instead of a textbox to display the messages. That way it doesn't matter how many messages there are, they will just keep getting added to listbox.
Something like:
For Each s as String in messageList
listbox1.items.add(s)
Next
Edit:
Retrieve the data and then bind it to the listbox - I've never really worked with mysql so I've lifted the code from a google search - it should get you started though.
dim table as new DataTable("table1")
' Create a Connection
using conn as new MysqlConnection("...connectionstring")
conn.Open() ' Open it
' Create a new Command Object
using cmd as new MysqlCommand("SELECT ID, Title, Body, Date, FromUsername FROM Message WHERE (ID LIKE #ID)", conn)
' Create a DataAdapter
' A DataAdapter can fill a DataSet or DataTable
' and if you use it with a CommandBuilder it also
' can persist the changes back to the DB with da.Update(...)
using da as new MysqlDataAdapter(cmd)
da.Fill(table) ' Fill the table
end using
end using
end using
' A Binding Source allows record navigation
dim bs as new BindingSource(table, nothing)
' You can bind virtually every property (most common are "text" "checked" or "visible"
' of a windows.forms control to a DataSource
' like a DataTable or even plain objects
ListBox1.DisplayMember = "Message"
ListBox1.ValueMember = "ID"
ListBox1.DataSource = table2

Related

Problem in Data display from database using datagridview in vb.net

Im using vb.net windows forms, VS 2019, .net framework 4.7.2 and mysql.
I tried datagridview in a form to display data from my database and its working perfectly fine.
But,
when i tried to use the same procedure, displaying data from the same database using datagridview in a child form (which i call via parent form that docks the child form over a region in parent form), it is not displaying any data, while the query works perfectly fine, its updating the data in database, but the data isn't displaying in this parent-child case.
Tho, the same code works perfectly fine and displays data if its used in a separate form.
I don't know what is the problem actually.
I had to attach more than one picture to explain clearly so i uploaded them and the link is given as:
https://imgur.com/a/6xka1B4
But, i have merged all the snips of the code from different forms as well:
1 The sub-class Custom_LoadDataGrid is called here and working correctly and displaying data in the gridview
DB.Custom_LoadDataGrid("SELECT item_name as 'NAME', item_price as 'PRICE', quantity as 'QUANTITY', Amount as 'AMOUNT' FROM transaction WHERE client_name ='" + Label11.Text.ToString + "'")
DB.myConnection.Close()
2 The sub Custom_LoadDataGrid which was called above
Public Sub Custom_LoadDataGrid(ByVal search As String)
Try
connString = "server=127.0.0.1;Port=3306;Database=smartcart;Uid=root;Pwd="
myConnection.ConnectionString = connString
myConnection.Open()
sql = search.ToString
DataAdapter = New MySqlDataAdapter(sql, myConnection)
Datacmd = New MySqlCommand(sql, myConnection)
DataAdapter.Fill(DataSet, DbName)
MaxRows = DataSet.Tables(DbName).Rows.Count
Dim dt1 As New DataTable
DataSet.Tables.Add(dt1)
DataAdapter.Fill(dt1)
Portal.Guna2DataGridView1.DataSource = dt1.DefaultView
ReleaseDb()
Catch ex As Exception
MsgBox("Something went wrong")
End Try
End Sub
3 i made this sub-class to call child forms and dock in the region somewhere in the parent forms
Private Sub OpenChildForm(childForm As Form)
'Open only form'
If currentChildForm IsNot Nothing Then
currentChildForm.Close()
End If
currentChildForm = childForm
'end'
childForm.TopLevel = False
childForm.FormBorderStyle = FormBorderStyle.None
childForm.Dock = DockStyle.Fill
Controls_panel.Controls.Add(childForm)
Controls_panel.Tag = childForm
childForm.BringToFront()
childForm.Show()
End Sub
4 here the child form is called
Private Sub Stock_manag_button_Click(sender As Object, e As EventArgs) Handles Stock_manag_button.Click
Sub_menu_panel.Hide()
ActivateButton(sender)
OpenChildForm(New Stock_management)
End Sub
5 This sub-class Custom_Load_DataGrid is called here but is not displaying data in gridview
DB.Custom_Load_DataGrid("SELECT * FROM addition_stock ")
DB.myConnection.Close()
'6 the sub-class Custom_Load_DataGrid is exactly same as Custom_LoadDataGrid (but obviously with different variables and relavent form name)
but this is not displaying data in gridview just in this this case of parent-child forms tho this one works fine too when used for seperate
forms.
Public Sub Custom_Load_DataGrid(ByVal search As String)
Try
connString = "server=127.0.0.1;Port=3306;Database=smartcart;Uid=root;Pwd="
myConnection.ConnectionString = connString
myConnection.Open()
sql = search.ToString
DataAdapter = New MySqlDataAdapter(sql, myConnection)
Datacmd = New MySqlCommand(sql, myConnection)
DataAdapter.Fill(DataSet, DbName)
MaxRows = DataSet.Tables(DbName).Rows.Count
MsgBox(MaxRows.ToString)
Dim dt2 As New DataTable
DataSet.Tables.Add(dt2)
DataAdapter.Fill(dt2)
Stock_addition.Guna2DataGridView1.DataSource = dt2.DefaultView
ReleaseDb()
Catch ex As Exception
MsgBox("Something went wrong")
End Try
End Sub
Can I get you to do this, in a new project, as a mini tutorial to make your life easier:
make a new project
Add a Form
Add a DataSet
Open the DataSet, right click in the surface and add a tableadapter
create a connection string to store in the settings: Pick mysql connector (note for this to work you need mysql connector AND ALSO mysql for visual studio https://dev.mysql.com/downloads/windows/visualstudio/ ) and fill in the details to create a database connection string make sure the test connection succeeds
proceed through the wizard choosing "query that returns rows", "by sql", enter a query of SELECT * FROM addition_stock WHERE ID = #id
write names of FillByID, and GetDataByID
finish
You'll see something that looks like a database table appear, with a thing called addition_stockTableAdapter underneath it
Right click the tableadapter, choose add .. query
add another query that is more relevant to how you will search this table, like maybe SELECT * FROM addition_stock WHERE stock_code = #stockCode
call it FillByStockCode/GetDataByStockCode
always give relevant names to your fill/get data methods
Always make the first query that creates the datatable/tableadapter pair a "select where id =" - it makes things easier later on. Add as many additional queries as you will need
Do the same thing again (Add a tableadapter) this time with a table that is either a parent or a child of addition_stock - it doesn't matter which, I'm just trying to demonstrate something here. Make sure you use a table that has a foreign key in the database, to addition_stock
Once you add your other datatable/tableadapter pair that is related to addition_stock you will see a line connecting the two datatables
Right click this line and choose "show relation labels" to display the name of the relation - it comes from the foreign key in the database
Now we are going to add a convenience method to load child data based on the parent id
Right click your child tableadapter and choose Add Query
add a query of SELECT * FROM tablenamehere WHERE parentidcolumnnamehere = #parentid and call it a suitable FillByXxx - obviously Replace the table name, column name and xxx with real values
save your DataSet and switch to the forms designer
show the Data Sources window (view menu.. other windows)
expand all the nodes of your DataSet - you'll see a parent table and two child tables, one underneath the parent, one not
drag the parent table out of datasources and onto the form - a datagridview with columns will appear, as will a tableadapter, bindingnavigator, DataSet and a bindingsource in the tray at the bottom. The nav has a textbox you can write an id into and a button to press. The datagridview columns are set up appropriately and the grid is bound to the bindingsource. The bindingsource is bound to the DataSet parent table.
run the app, enter an ID in the textbox, click fill, edit the name of something, click save, go use mysql workbench to look in the db. Super; you can download, edit and save db data and you haven't written a single line of code; you're just using the thousands of lines of code visual studio has written for you.
stop the app, go back to the forms designer
drag the child table that is underneath the parent table onto the form. More items appear - a datagridview bound to another bindingsource, another navigator etc. You can delete this second navigator- we won't use it
take a look at the bindingsource of the child table - note that it is NOT bound directly to the DataSet but instead it is bound to the other bindingsource, with a DataMember property that is set to the name of the relation line between the two tables
switch to code view and look at the code of the Fill toolstripmenu that fills the parent record by the id/whatever. If there is any redundant code from the child bindingnavigator, remove it (or comment it out: it could be slightly useful for the next step
under the line of code that fills the parent datatable by id put the following code:
childTableAdapter.ClearBeforeFill = False
yourDatasetName.ChildTableName.Clear()
For Each parentRow in yourDataSetName.YourParentTableName
childTableAdapter.FillByParentId(yourDataSetName.ChildTableName, parentRow.Id)
Next
Run the app again, enter the parent id, click fill. The parent data and the related child data loads. Great, but the real magic happens when we load multiple parent rows. Go back to code and swap the FillById on the parent tableadapter for the other query you write (if you didn't do one, go back to DataSet, Add a query to the parent table adapter that loads multiple rows, like select * from person where lastname = #lastname so we can enter a last name like smith, of which there are many) so now your code looks like this in the fill:
parentTableAdapter.FillBySonethingThatGetsMultipleRows(yourDataSetName.ParentTableName, fillByTextboxName.Text)
childTableAdapter.ClearBeforeFill = False
yourDatasetName.ChildTableName.Clear()
For Each parentRow in yourDataSetName.YourParentTableName
childTableAdapter.FillByParentId(yourDataSetName.ChildTableName, parentRow.Id)
Next
You'll note that you get multiple parent rows, you load multiple sets of child rows in the loop, but when you run the app and you choose a different parent in the parent grid the child grid automatically filters to show only the children of the currently selected parent

Displaying data from a mysql server on a datagridview object. is not displaying anything

I have tried making a dataset using the dataset tool to link it on the design side however that hasn't worked as it keeps disappearing and this is the other way it does not display any values on the datagrid view i am unsure why and i am fairly new to this side of vb so if you could explain it as well that would be great. Thanks in advance.
Imports MySql.Data.MySqlClient
Public Class Search
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Try
If TextBox1.Text = "" Then 'this acts as a simple presence check on the textbox
Else
Dim val = "name"
If RadioButton1.Checked = True Then 'This changes the type of search i do as it filters which column the query looks in
val = "type"
End If
Await getDataSet(TextBox1.Text) ' waits for infomation to be retrieved
End If
Catch ex As System.Exception
System.Windows.Forms.MessageBox.Show(ex.Message) 'Catches any errors
End Try
End Sub
Async Function getDataSet(partname As String) As Task(Of DataSet) 'This retrieves the values that matches the users input
Return Await Task.Factory.StartNew(
Function()
Dim connectionString = "server=localhost; userid=root; password=; database=partstest1; CharSet=utf8;" 'These are the login details for the database in the form of a connection string
Dim commandText = "SELECT ID, Benchpoint, Name, Type, BrandID FROM `parts` WHERE `name` Like '%" & TextBox1.Text & "%';"
Using connDB = New MySqlConnection(connectionString), objCmd = New MySqlCommand(), objAdpt = New MySqlDataAdapter()
connDB.Open()
objCmd.Connection = connDB
objCmd.CommandText = commandText
objCmd.CommandType = CommandType.Text 'These lines specify the command i am using and execute it
objAdpt.SelectCommand = objCmd
Dim objDs = New DataSet()
objAdpt.Fill(objDs) 'Puts all of the values into a dataset
PartsDataGridView.DataSource = objDs.Tables(0) 'This shows the datasource and displays it
Console.WriteLine(objDs)
Return objDs
End Using
End Function)
End Function
End Class
Install MySQL/connector/etc
Install MySQL for Visual Studio (needed to get it to show as a datasource in VS) - https://dev.mysql.com/downloads/windows/visualstudio/
Add a new dataset to your project
Double click the dataset, right click the surface of it, choose Add >> TableAdapter
Choose existing connection or New Connection if you have no existing. Choose MySQL Database (install MySQL for Visual Studio from step 2 if this is absent)
Enter server details, choose to save the password, back in the wizard choose Yes, include sensitive.. and click Next, choose Yes, save the connection string, click Next, choose Use SQL Statements, Next, enter a suitable query that selects based on the primary key such as SELECT * FROM yourtable WHERE id = #id, Next, call the methods FillById and GetDataById to distinct them from other queries you may add later like FillByCity or GetDataByStatus. At the end of this wizard you should have a datatable and tableadapter that looks like your database table:
Switch to the form designer, and also ensure that the Data Sources window is visible (click View Menu >> Other Windows >> *Data Sources**), expand all the nodes in the Data Sources panel
Drag the node representing your table (mine is called person) out of the datasources window and drop it on the form. Several things will appear:
a datagridview already bound to the dataset's datatable showing person data,
a toolstrip with a textbox for inputting the ID (remember you made a query that takes a parameter),
another toolstrip with navigators and a save button),
a dataset (needed to store the data),
a bindingsource (acts as a link between the dataset's datatable and the grid, knows what current record is showing, allows sorting and filtering),
a tableadapter (an enhanced data adapter that will pull data from the db into the dataset and send back any changes),
a tableadapter manager (a device that knows what order to run updates in for hierarchical data)
Also, as a demonstration of how it works, drag all the nodes UNDERNEATH person onto the form also - you can see they have different icons. They will re-use most of the components on the form but you'll get textboxes, datetimepickers, checkboxes etc that are bound to the bindingsource and will hence show the current item from the underlying list (the datagridview shows them all, with an indicator of which row is current)
Run the project, type an ID into the textbox, hit **FillById*, write some new info into another row at the bottom - it will commit to the underlying dataset/datatable when you change row in the DGV, note that flicking back and forth between the rows in the DGV causes the textboxes to change as the notion of Current row is updated (navigating the grid, or clicking the arrows in the navigator changes the bindingsource .Current property, and all controls bind through the bindingsource
hit save - now go look in your db in MySQL Workbench - the new record is there. You've made a full databound UI, and not written a line of code - all the code is there in the FormX.vb if you want to see it - written for you by the designer. Take a look
Note that it still says -4 (in my UI) for the temp id; the program didn't download the new ID that was assigned by the DB. To make it do this, youre supposed to be able to go back to your dataset, right click the tableadapter, click Advanced Options, and tick on Refresh the datatable - this will cause the adapter to update any local IDs after it saves the row. IDs can cascade update if they are part of a datarelation between two datetables. In MySQL this doesn't work (I'm reporting a bug to them now), but you can make it work by manually editing the XML file representing the dataset (right click the DataSet in solution explorer, choose Open With.. Choose XML Editor, locate the insert statement eg:
INSERT INTO `person` (`Name`, `Birthdate`, `Salary`) VALUES (#p1, #p2, #p3)
Add another statement after it so it looks like:
INSERT INTO `person` (`Name`, `Birthdate`, `Salary`) VALUES (#p1, #p2, #p3)
;SELECT `Id`, `Name`, `Birthdate`, `Salary` FROM `person` WHERE `Id` = last_insert_id()
Now, saving the table will cause the UI to refresh with the ID values calculated by the auto increment in the DB

Try to open new tables, but recieving error [duplicate]

My friend wants to create a new table in the database (his using vb.net, mysql). The tricky thing is that he wants to name the new table from the input being encoded into a textbox.
Is that possible? To create and name a new table from the input in the textbox.
#njm
you can create one string variable having query of "Create table <name>(field1,field2....)"
In above query must be replace with your input text box.
And pass this string to mysql command variable having its own connection ...
And simply execute this query...
This code should work....
Add one button to the form for testing purpose and place the following code to its click event
Imports MySql.Data.MySqlClient
'place this in the class.............
Dim myConnectionString = My.Settings.MySQL_DBConnectionString
Dim con As New MySqlConnection(myConnectionString)
'Code on the button...........
Dim createSql As String
Try
con = New MySqlConnection(myConnectionString)
con.Open()
Dim tblname = "anyInputName"
createSql = "CREATE TABLE " & tblname & " (id INT(6) NOT NULL AUTO_INCREMENT,otherField TEXT NOT NULL,PRIMARY KEY (id));"
Dim cmd As New MySqlCommand(createSql, con)
cmd.ExecuteNonQuery()
cmd.Dispose()
Catch ex As Exception
MsgBox(ex.Message)
Finally
con.Close()
End Try
Now go experimenting.......
Certainly it can be done.
Basically you build a string witha Create Table statement in it and then execute it.
e.g.
someSql "Create Table " + EditBox1.Text + "(.....)"
BUT
Building sql from user input opens you to sql injection attacks.
Legal identifiers, certain characters can't be used, some must be escaped, the name may already be in use...
Once you have the table, how is the code going to use it, to know that there is a table called "MyTable" in the database, why it's there...
You wouldn't normally just hand out create table permissions.
What about dependencies (relations, stored procs, contraints etc)
There are several ways of dealing with this, one is to do table creation in another app, build up rules and store meta information somehow that the code can use to use the table.
Another for simpler apps, is to give the table some unique name in the db and then use the the name entered by the user as an alias for it, so Show("MyTable") gets mapped to Show("UserTable1876")
Another possibility is if the table has definite common structure and it's just user Fred's copy of it is to add another column to the table and then simply add Fred's UserID when any CRUD functions are used.
So yes it can be done, should it? Depends....

Set up Access table to perform multiple records at time

I performed some research how do I need to set up my DB but I need your advice how to.
I have few tables in my db ( db is for incoming material ) in this db are below tables:
Material table
incoming delivery
measurements
supplier
time measurement
Let me explain logic of this db.
When delivery come user will input some data in form (creation of incoming list) where he will basically enter all data necessary to start process of receiving. So once he hit button save record he will create record in tables incoming delivery and time measure.
Until this point everything works perfectly. When next user received this incoming list he got some data where was one hyperlink to file where they put it measurements.
And here come my problem.
I want data to be input in Access rather than to excel (form input looks much more better [yes this is most important reason :) ] ).
So for that I created table called measurements, where I plan input [incoming delivery ID], [material id], [primal key] , and that 41 another columns for measurement(this columns need to be separated cause we have many parts and each got different No. of measurement and user will get information via user form ( opening different form based on material id [this works]).
So after describing its logic I am requesting you people how do i create with 1 record to measurement table each time different numbers of measurements in measurements table for it.
put it even more simple just for case. When user hit button to save the record which creates record in delivery list will also create for example additional 5 records (this number will be based on cell value) in measurement table linked with incoming delivery. (relation is of course set up to one-many)
so in the end when i will create somehow continuous table for data input. User will see form where he got incoming delivery No. some information from other tables and as mentioned 41 items to measure 5 times ( 41 columns and 5 rows )
Hope that my explanation is clear and rly need your help i am screwed :D
Hints:
Use VBA to automate the creation of records. Look for information about DAO and/or ADO and how to use them to insert records (I personally use DAO when I work with Access, it works but it's old).
Do your homework. Before asking a question, it is important that you do your research and that you try to solve the problems by yourself. Try to help yourself before asking others. Please read this article.
Maybe this snippet of code can help you. You'll need to call this method from an event (button_clic or something in your form):
public sub addRecords(id as integer)
dim db as dao.database, rsIn as dao.recordset, rsOut as dao.recordset
dim strSQL as String
dim someValue as integer, i as integer ' Test values
' "Connect" to your current database
set db = currentdb
' Create a recordset with the input data you need (read only)
strSQL = "select * from tbl_inputTable where id=" & id
set rsIn = db.openrecordset(strSQL, dbOpenDynaset, dbReadOnly)
' Create a recordset to your output table
set rsOut = db.openRecorset("tbl_outputTable", dbOpenDynaset, dbAppendOnly)
' Read the data from the input table
with rsIn
.moveFirst
someValue = rsIn![aField]
end with
' Write some test data to your output table
with rsOut
for i = 1 to someValue
.addNew
rsOut![fk_id] = id
rsOut![theValue] = i
.update
next i
end with
' Close every recordset and databases (this does not close your application)
rsIn.close
rsOut.close
db.close
end sub
In your input form, write this in the "On Click" event:
sub button1_click()
call addRecords(txtId.value) ' I am assuming that there's a text box called "txtId"
end sub
This is just a sample of what you can do with DAO. I won't (and maybe nobody else would) write the full code for you: You'll need to fit this to your particular problem.

Multiple databases information display

I have a very difficult task, that I think exceeds my level of knowledge of databases. I am only learning it for a week, so I require help.
I currently have an old database that has tables for requests and customers. This information is currently displayed in ASP.NET
What I was required to do, was to connect a new database for users into this system, while keeping the tables for the requests in the old database. Thus it is using 2 databases. I have set it up so, when a user creates a new request, in the request tables it saves it with his userID from the new database, but when the table is being displayed, it uses this new userID to find the user information from the old customers table. Thus I ended up with this:
Sub BindDataGrid()
cmdoledb = New SqlCommand("SELECT r.customerid, r.RequestID, R.RequestDate, R.RequestDescription, a.AssignedTo, r.Urgency, r.ExCompletionDate from tbl_requests r, tbl_assignedto a where r.statusid = 1 and r.assignedtoid= a.assignedtoid ", objConn)
objConn.Open()
Dim rdr As SqlDataReader
Dim myItem As ListItem = New ListItem()
rdr = cmdoledb.ExecuteReader(0)
While rdr.Read()
myItem = New ListItem()
myItem.Value = rdr.GetInt32(0)
cmddb = New SqlCommand("SELECT SESFirstName + ' ' + SESLastName As fullname from SESLogin where SESLoginID = #customerID", objConnect)
cmddb.Parameters.AddWithValue("#customerID", myItem.Value)
objConnect.Open()
Dim anotherAdapter As New SqlDataAdapter(cmddb)
Dim dss As New DataSet
anotherAdapter.Fill(dss)
dgrdUsers.DataSource = dss
objConnect.Close()
End While
Dim myAdapter As New SqlDataAdapter(cmdoledb)
Dim ds As New DataSet
myAdapter.Fill(ds)
dgrdUsers.DataSource = ds
dgrdUsers.DataBind()
objConn.Close()
End Sub
Currently it displays nothing, and gives out an error for myItem.Value = rdr.GetInt32(0) being a Null. I went through it step by step and it loads customerids normaly into the myItem.Value, but when they run out, it is supposed to exit, but keeps going, thus giving an error.
This code is very silly i know, but with my knowledge, this is what I was able to come up with. Thus I require your help and advice, to fix this issue I am having.
Well, the first thing I would do is combine your two databases into one (preferably using views as replacements for you existing tables), if indeed you are using two dbs (it's not clear from your code sample whether you really are using two dbs or simply additional tables).
You are executing you primary query twice, once for a data reader and once for a dataadapter.fill. You should do the fill first and then iterate over the resulting rows. The code sample is using a list item in oreder to contain a single integer, unless you are not showing all of your code, you should just use an integer variable.
I don't know if it fits in with what you are doing or not, but you only need one dataset with two tables to contain the data you are retrieving.