Adding Combobox items from SQL Server using single (and varying) column - sql-server

First question here, and forewarning I am very new to programming in general, just trying to figure the basics out.
Basically what I am trying to do is select all items in a specified list from my SQL server, add them to an array and then fill a combobox with that array.
The SQL server structure is as follows:
Just a representation
The user will select which product they are building when they log in, and then I would like a combobox to be filled with all of the parts that pertain to that item.
The current code sample
Public Class frmProduct
Private Sub frmProduct_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mycon As SqlConnection = New SqlConnection('connection string')
mycon.Open()
Using mycon
Dim prodlist As String = frmMain.cmbProduct.SelectedItem
Dim cmds As String = "SELECT DISTINCT(Product) FROM [Products] where Product = #prodlist"
Dim cmde As New SqlCommand(sqlt, mycon)
cmde.Parameters.AddWithValue("#Product", prodlist)
Dim dr As SqlDataReader = scmd.ExecuteReader
If dr.HasRows() Then
cmbFailure.Items.Add(dr.GetString(0))
End If
scmd.ExecuteNonQuery()
End Using
End Sub
End Class
The user selects the Product on the login form, and the selected product is carried over to the parts list form.
The error I am currently recieving which is likely the first of many is "Invalid Column Name Product". I thought that the issue might be that the selected product is not carrying over, but I added a label which I am changing the text to be equal to "prodlist" and it accurately changes the label text.
Again I am fresh meat at all of this, so I apologize for any obvious blunders. Thank you for your help!

In the image you attached the "Product1, Product2, Product3" are fixed columns?
If are, you have to use these columns in your select statement. This is a bad design but will work.
I assume that's a study exercise, so later, can you enhance your project adding 2 tables, one for products and other for store parts of products.

For information about the code.
Private Sub frmProduct_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim mycon As SqlConnection = New SqlConnection('connection string')
Dim cmds As String = "SELECT DISTINCT(Product) FROM [Products] where Product = #prodlist"
Try
' Most of the DB will having a connection fail, so programmer must set a try catch for it '
mycon.Open()
Using mycon
Dim prodlist As String = [Form].[ComBoBox].SelectedItem
Dim cmde As New SqlCommand(sqlt, mycon)
cmde.Parameters.AddWithValue("#Product", prodlist)
Dim dr As SqlDataReader = scmd.ExecuteReader
If dr.HasRows() Then
cmbFailure.Items.Add(dr.GetString(0))
End If
scmd.ExecuteNonQuery()
' For more save for this sql will execute successfully, some of programmer will use Transaction with commit '
' Microsoft Link: https://msdn.microsoft.com/en-us/library/5ha4240h(v=vs.110).aspx '
End Using
' mycon.Close() '
Catch ex As Exception
MessageBox.Show(ex.Message) ' Exception Message '
' [Optional]Release object '
' mycon.Close() '
End Try
End Sub
And for your items with it may crash the result, due to scmd was not same as cmde.
Would you please explain [scmd] is stand for?

Related

Inserting data into database with autonumber in VB.net

I'm trying to insert data into a database with an autonumber in MS Access as primary key. I get an error saying "Number of query values and destination fields are not the same. The data types in MS Access are Autonumber (I didn't include it in the INSERT statement), String (#OrderNo), String (#Product), Number (#Qty), and Date (#TDate). Here's the image:
Here's my code:
For Each row As DataGridViewRow In DataGridView1.Rows
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=Daily Inventory.accdb;"
Using conn As New OleDbConnection(connString)
Using cmd As New OleDbCommand("Insert into Table1 Values(#OrderNo, #Product, #Qty, #TDate)", conn)
cmd.Parameters.AddWithValue("#OrderNo", TxtOrder.Text.ToString)
cmd.Parameters.AddWithValue("#Product", row.Cells("Product").Value)
cmd.Parameters.AddWithValue("#Qty", row.Cells("Qty").Value)
cmd.Parameters.AddWithValue("#TDate", Date.Now.ToString("MM/dd/yyyy"))
If conn.State = ConnectionState.Open Then
conn.Close()
End If
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
Next
You need to change your sql to "Insert into Table1 (OrderNo,Product,Qty,TDate) Values(#OrderNo, #Product, #Qty, #TDate)".
The following code works for me.
DataGridView1.AllowUserToAddRows = False
For Each row As DataGridViewRow In DataGridView1.Rows
Dim connString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=...;"
Using conn As New OleDbConnection(connString)
Using cmd As New OleDbCommand("Insert into Table1 (OrderNo,Product,Qty,TDate) Values(#OrderNo, #Product, #Qty, #TDate)", conn)
cmd.Parameters.AddWithValue("#OrderNo", TxtOrder.Text.ToString)
cmd.Parameters.AddWithValue("#Product", row.Cells("Product").Value)
cmd.Parameters.AddWithValue("#Qty", row.Cells("Qty").Value)
cmd.Parameters.AddWithValue("#TDate", Date.Now.ToString("MM/dd/yyyy"))
If conn.State = ConnectionState.Open Then
conn.Close()
End If
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Using
End Using
Next
Well, I think we dealing with a bit of a chicken and a egg problem here?
I mean, how did the grid get created?
How and where did you setup the columns in the grid?
lets drop a data grid view into a form. Drop in a button.
We have this code to load up the grid:
Private Sub HotelGridEdit_Load(sender As Object, e As EventArgs) Handles Me.Load
LoadGrid()
End Sub
Sub LoadGrid()
Using conn As New OleDbConnection(My.Settings.AccessDB)
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description, Active FROM tblHotelsA
ORDER BY HotelName"
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
Dim rstData As New DataTable
rstData.Load(cmdSQL.ExecuteReader)
DataGridView1.DataSource = rstData
End Using
End Using
End Sub
So, now we have this:
Now, in a above, I can cursor around - make any edits I want.
I can also type in on the bottom blank row to add new rows.
I can click on the left side recordselector, and hit delete key.
Now, to save my edits, save my addtitions, and save my deletes?
I have the one button at the top, and this code works to do all updates, all addtitions, and all deletes.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' save all edits, and new rows, and deletes
Using conn As New OleDbConnection(My.Settings.AccessDB)
Dim strSQL As String =
"SELECT ID, FirstName, LastName, City, HotelName, Description, Active FROM tblHotelsA"
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
Dim da As New OleDbDataAdapter(cmdSQL)
Dim daC As New OleDbCommandBuilder(da)
da.Update(DataGridView1.DataSource)
End Using
End Using
End Sub
So, not a lot of code.
In fact, often using a data table is a lot less work, since you don't have to mess with all those parameters anyway - even if your data grid was somehow not feed from the database. But, if you feeding the "grid" from the database, then really, you can just add rows - and then write some code to send the changes back to the database with the above code. And if you want to start out with a blank grid - not show previous rows, then just add to your sql like this:
SELECT * from tblHotels WHERE ID = 0 Order by Hotelname
Use above to create a data table without any rows but STILL bind that to the grid, and thus once again, to add, or delete rows, you just edit and add them, and again the SAME code I had above will work to save edits, deletes and additions.

How to display all elements in a column using cmd.ExecuteReader from mdf data file in Visual Basic

Here's my .mdf database file that has 5 columns
I want to add each of those values from my Id column in a list
Private Sub Read_Click(sender As Object, e As EventArgs) Handles Read.Click
Try
If con.State = ConnectionState.Open Then
con.Close()
End If
con.Open()
cmd = con.CreateCommand()
cmd.CommandType = CommandType.Text
cmd.CommandText = "SELECT Id FROM tablekongbago"
cmd.ExecuteNonQuery()
Dim dr As SqlClient.SqlDataReader
dr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While dr.Read
element = dr.GetInt32(0).ToString()
End While
Catch ex As Exception
End Try
MessageBox.Show(element)
End Sub
The problem is that I can only retrieve the last row of my Id column and not all of the values from my Id column using
element = dr.GetInt32(0).ToString()
If I try to iterate and turn it into
dr.GetInt32(1).ToString()
it displays nothing.
I want to create a collection of Id's to a List(Of Integer) I know how to create a list and a for loop but I don't know how can I retrieve all of my Id's from my Id column, what kind of code should I use if "dr.GetInt32(0)" is only for the last row of the Id column?, is there a way I can loop starting from the very first top row up to the last row of my Id column? I want something like "list[0] - referring to the first row and list[2] - referring to the last row, so that I can add it my List(Of Integer).
I cringe whenever I see If con.State = ConnectionState.Open Then. Connections should be declared in the method where they are used. You should never have to question the ConnectionState.
You have executed your command twice. A Select in not a NonQuery. NoQuery is Insert, Update and Delete.
Your While loop keeps overwriting the element varaiable on each iteration so you only get the value in the last record.
Never write an empty Catch block. It will just swallow errors and you may get unexpected results with no clue why.
It is a good idea to separate you database code from you user interface code.
Create your connection and command with a Using...End Using block so you know they are properly disposed. Likewise with the reader. I like to do as little as possible with a reader because it requires and open connection and connections should be open for as short a time as possible.
Private ConStr As String = "Your connection string"
Private Sub Read_Click(sender As Object, e As EventArgs) Handles Read.Click
Dim dt As DataTable
Try
dt = GetIds()
Catch ex As Exception
MessageBox.Show(ex.Message)
Return
End Try
Dim ListOfIDs = (From row As DataRow In dt.AsEnumerable
Select CInt(row(0))).ToList
ListBox1.DataSource = ListOfIDs
End Sub
Private Function GetIds() As DataTable
Dim dt As New DataTable
Using con As New SqlConnection(ConStr),
cmd As New SqlCommand("SELECT Id FROM tablekongbago;", con)
con.Open()
Using reader = cmd.ExecuteReader
dt.Load(reader)
End Using
End Using
Return dt
End Function
You can simply create a List of Integer and add the ids to your collection during each call to dr.Read()
Dim ids = New List(Of Integer)()
While dr.Read()
ids.Add(dr.GetInt32(0))
End While
You code looks a bit messed up. This should work:
Note that a sql command object is VERY nice.
It has a reader built in - you don't need to define one
It has the command text - you don't need to define one
it has a connection object - again no need to create one (but you look to have one)
And using a dataTable is nice, since you can use for/each, or use the MyTable.Rows(row num) to get a row.
And a datatable is nice, since you don't need a loop to READ the data - use the built in datareader in sqlcommand object.
Using cmdSQL As New SqlCommand("Select Id FROM tblekingbago", con)
cmdSQL.Connection.Open()
Dim MyTable As New DataTable
MyTable.Load(cmdSQL.ExecuteReader)
' table is now loaded with all "ID"
' you can see/use/display/play/have fun with ID like this:
For Each OneRow As DataRow In MyTable.Rows
Debug.Print(OneRow("Id"))
Next
' display the 5th row (it is zero based)
Debug.Print(MyTable.Rows(4).Item("Id"))
End Using

Using Variables for Table and Column in LINQ

So I am writing a VB.Net that is using LINQ to access a database. There is one part of the program that I have been having trouble figuring out, how to access a column in a table when both values are passed as variables.
Right now I have a setup using SqlConnection strings and SqlDataAdapters to get the job done, but this is literally the only segment of my code that uses this syntax and it bothers the hell out of me. I'd like to figure out how to change the code to a LINQ format so that I have the code base feeling more cohesive.
This is the code segment I have right now:
Public Function GetColumnFromTable(col As String, tbl As String) As AutoCompleteStringCollection
Dim source As New AutoCompleteStringCollection
Dim conn As New SqlConnection("my connection string")
Try
conn.Open()
Catch ex As Exception
MessageBox.Show(ex.Message)
Return source
End Try
Dim query As New SqlCommand("SELECT " + col + " FROM " + tbl + "", conn)
Dim dataSource As New DataTable
Dim adapter As New SqlDataAdapter(query)
adapter.Fill(dataSource)
For i = 0 To dataSource.Rows.Count - 1
source.Add(dataSource.Rows(i)(field).ToString())
Next
conn.Close()
Return source
End Function
The code is meant to grab the rows from a specific column in a table and set them to an AutoCompleteStringCollection that is used as the autofill for text boxes on the GUI. I would like to be able to change it to something like this.
Public FUnction GetColumnFromTable(col As String, tbl As String) As AutoCompleteStringCollection
Dim source As New AutoCompleteStringCollection
Dim query = From tbl Select col
query.ToList().ForEach(Function(x) source.Add(x))
End Function
I'd like something like the above code that actually works, but I don't know how to do it.

how to display a selected item on a list box (from an access database) to a text box?

Hi I'm trying to display a selected product on a listbox similar in this video:
https://www.youtube.com/watch?v=QbbZzaMZGhY
In the video, when he click an item from the listbox, its values appear(price and name) on the textbox. I reviewed the source code but he was not using a database. In my case, I need to use an access database to list all of my product and their id and price. Here's what I got so far from asking here:
Private Sub listboxitems_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listboxitems.SelectedIndexChanged
Using lbconn As New OleDb.OleDbConnection("PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source = C:\Users\USER PC\Desktop\orderDB1.accdb")
Using lbcmd As New OleDb.OleDbCommand("SELECT productid, product, price FROM productlog WHERE productid = ? AND product = ? AND price = ?", lbconn)
'Set your values here. The parameters must be added in the same order that they
'appear in the sql SELECT command
Dim prodidparam As New OleDbParameter("#productid", Me.txtproductid.Text)
Dim prodparam As New OleDbParameter("#product", Me.txtproduct.Text)
Dim priceparam As New OleDbParameter("#price", Me.txtprice.Text)
lbcmd.Parameters.Add(prodidparam)
lbcmd.Parameters.Add(prodparam)
lbcmd.Parameters.Add(priceparam)
'Open the connection
lbconn.Open()
txtproduct.Text = listboxitems.SelectedItem
Using lbreader As OleDbDataReader = lbcmd.ExecuteReader()
While lbreader.Read
txtproductid.Text = lbreader.GetInt32("productid").ToString()
txtproduct.Text = lbreader.GetString("product")
txtprice.Text = lbreader.GetString("price").ToString()
End While
End Using
End Using
End Using
End Sub
In the line:
txtproduct.Text = listboxitems.SelectedItem
I managed to show its name in the textbox, but its not coming from my database. I can't just type their price and name in the project but I need my data source to come from the database. So far nothing is showing up in the app. What am i missing? Thanks.
EDIT: The form load code where the listbox is filled with the database.
Private Sub shop_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'Create a connection to the database
provider = "PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source="
datafile = "C:\Users\USER PC\Desktop\orderDB1.accdb"
connString = provider & datafile
myConnection.ConnectionString = connString
'Open the connection with error handling
Try
If Not myConnection.State = ConnectionState.Open Then
End If
myConnection.Open()
Catch OleDbExceptionErr As OleDbException
MessageBox.Show(OleDbExceptionErr.Message)
Catch InvalidOperationErr As InvalidOperationException
MessageBox.Show(InvalidOperationErr.Message)
End Try
'Command Object. Select from productlog. 'productlog name of table'
Dim objcmd As New OleDbCommand("SELECT * FROM productlog", myConnection)
'data adapter and data table.
Dim da As New OleDbDataAdapter(objcmd)
Dim dt As New DataTable("productlog")
da.Fill(dt)
'Create connection and release resources
myConnection.Close()
myConnection.Dispose()
myConnection = Nothing
objcmd.Dispose()
objcmd = Nothing
da.Dispose()
da = Nothing
'fill from access to the listbox
For Each row As DataRow In dt.Rows
listboxitems.Items.Add(row.Item("product"))
Next
'Release resources
dt.Dispose()
dt = Nothing
End Sub
EDIT: CODE UPDATED
Private Sub listboxitems_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles listboxitems.SelectedIndexChanged
Using lbconn As New OleDb.OleDbConnection("PROVIDER=Microsoft.ACE.Oledb.12.0; Data Source = C:\Users\USER PC\Desktop\orderDB1.accdb")
Using lbcmd As New OleDb.OleDbCommand("SELECT productid, product, price FROM productlog WHERE product = ?", lbconn)
'Set your values here. The parameters must be added in the same order that they
'appear in the sql SELECT command
Dim prodparam As New OleDbParameter("#product", listboxitems.SelectedItem)
Dim prodidparam As New OleDbParameter("#productid", listboxitems.SelectedItem)
Dim prodpriceparam As New OleDbParameter("#price", listboxitems.SelectedItem)
lbcmd.Parameters.Add(prodparam)
lbcmd.Parameters.Add(prodidparam)
lbcmd.Parameters.Add(prodpriceparam)
'Open the connection
lbconn.Open()
txtproduct.Text = listboxitems.SelectedItem
Using lbreader As OleDbDataReader = lbcmd.ExecuteReader()
While lbreader.Read
txtproductid.Text = listboxitems.SelectedItem.ToString()' iknow im missing alot in this line of code i just dont know what that is'
txtproduct.Text = listboxitems.SelectedItem.ToString()
txtprice.Text = listboxitems.SelectedItem.ToString()
End While
End Using
End Using
End Using
End Sub
I changed the get statements cause im having an error that says cannot convert type integer to string. im sorry if im making this really hard stack overflow is like my first line of defense and my last resort at the same time.
Your query is wrong. You want to get back the productid, product and price from the productlog table WHERE the record searched is equal to the productid, product and price that you supply as parameters.
Did you see the problem?
If you already know these values why ask the database? I suppose that your task is to find the product and price given the product stored in the current list item. If so, there is no need to use the textboxes and your query should be
SELECT productid, product, price FROM productlog WHERE product = ?
And the parameter is the data extracted by the listbox item
Dim prodidparam As New OleDbParameter("#product", listboxitems.SelectedItem)
Now your code could reach the while loop and set the textboxes with the missing informations. Of course this works because you have distinct product names in your table (meaning, there are no two records with the same product name)
EDIT
Looking at your comments below it seems that you are really confused how to use the GetPos, GetString, GetInt32 and eventually GetDecimal.
Once you have called lbreader.Read() you have a record at your disposition to transfer into your textboxes. But there is little point to take in consideration. You should call the various GetXXXX appropriate for the datatype of the underlying column. This problem is often overlooked by VB.NET programmers used to the automatic type conversion applied by the VB.NET compiler. These conversions don't exist in the lower levels of NET and it is better to avoid these conversions at all to not fall in subtle problems.
However, to call a OleDbDatareader.GetXXXX you need the ordinal position of the field in the returned record. So you need to call first OleDbDataReader.GetPos and then use the value returned by GetPos to extract the info from the GetXXXXX call.
Using lbreader As OleDbDataReader = lbcmd.ExecuteReader()
While lbreader.Read
Dim pos = lbreader.GetPos("product")
txtProduct.Text = lbreader.GetString(pos)
pos = lbreader.GetPos("productid")
txtProductID.Text = lbreader.GetInt32(pos).ToString()
pos = lbreader.GetPos("Price")
txtPrice.Text = lbreader.GetDecimal(pos).ToString()
End While
End Using
The last line uses GetDecimal assuming the column Price to be a numeric decimal in your database (as it should being it a currency value), if not, then use the appropriate GetXXXXX. Note also that the two last GetXXXX returns an Int32 and a Decimal. To assign these values to a property of type string (like Text) you should use an explicit conversion to a string (ToString())

How to randomly select multiple choice questions from Access database

I have an Access Database containing about 30 questions. The database is divided in 3 tables; Questions, Possible Answers and Answer.
The questions have from 2 to 5 possible answers.
How can I randomly select 10 questions from my database and add them to my vb form?
PS: This is my first time doing this
Here is my code
Dim provider As String
Dim dataFile As String
Dim connString As String
Public myConnection As OleDbConnection = New OleDbConnection
Public dr As OleDbDataReader
Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
provider = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source ="
dataFile = "C:\Users\Phil\Desktop\Questions.accdb"
connString = provider & dataFile
myConnection.ConnectionString = connString
myConnection.Open()
Dim str As String
str = "SELECT Top 10 ID_Question From Questions ORDER BY RND(ID_Question)"
Dim cmd As OleDbCommand = New OleDbCommand(str, myConnection)
dr = cmd.ExecuteReader
While dr.Read()
TextBox1.Text = dr("ID_Question").ToString
End While
myConnection.Close()
MsgBox("fsafa")
End Sub
The Textbox does not change and the msgBox does not show
Solution that worked for me if anyone is interested
SELECT Top 10 ID_Question, Question_Name
FROM tblQuestions
ORDER BY RND(-(100000*ID_Question)*Time())
I have to assume that your questions have an AutoNumber field, your possible answers has a one-to-many join based on that AutoNumber field and your answers have a one-to-one join based on that AutoNumber field? That would be the best way to associate the tables.
If so, try something like this:
SELECT Top 10 Question_ID FROM tblQuestions ORDER BY RND(Question_ID)
This should give you the top 10 randomly selected Question_IDs (or whatever you're calling that AutoNumber field I spoke about above), and then you can left join to the Questions/Possible Answers/Answers tables based on that ID. You would simply populate a form or subform based on the SQL above in order to display the questions.

Resources