Unwanted name column in DataGridView - How can I get rid of it? - vb.net

I'm making a WinForms application using VB.NET. I have a DataGridView that I am using to display results of a query to an SQL-Server Database. This works fine:
Dim SQL As New SqlConnection()
Dim CMD As New SqlCommand()
Dim ADP As New SqlDataAdapter()
Dim TBL As New DataTable()
SQL.Close()
SQL.ConnectionString = "Server=" & GetServerIP() & ";Database=" & GetDB() & ";User Id=" & userID & ";Password=" & pass & ";"
CMD.Connection = SQL
CMD.CommandText = "SELECT * FROM " & table
SQL.Open()
ADP.SelectCommand = CMD
TBL.Clear()
ADP.Fill(TBL)
DataGridView1.DataSource = TBL
The issue is that the DataGridView has a column NAME which is empty in every row.
I tried changing the query to SELECT SEQ_NUM FROM CONFIG_SYS that resulted in a DataGridView with a NAME and SEQ_NUM column. I tried calling DataGridView1.Columns.Clear() before the DataGridView1.DataSource = TBL and that does not have an effect on anything. I should mention that if I query any table in my database that does not have a NAME column, I get the same results with an empty NAME column in my DataGridView.
My theory is that a DataGridView automatically adds NAME as the first column, expecting the Database Table to be set up with a NAME column as the primary key. However, my table does not have NAME, it has a column called SEQ_NUM as the primary key. I am able to work around this by doing DataGridView1.Columns("NAME").Visible = False but I don't feel that this is the best way to do it.
Is there a better way to handle this - I'd like the column to not exist at all in the data grid, not just not be visible.

What was causing my issue was the fact that I was calling TBL.Clear() incorrectly.
Calling DataTable.Clear() will clear the Data from a DataTable but it will leave the columns in place.
Instead I should have been calling TBL.Columns.Clear(), which gets rid of the columns of the DataTable. However, using Breakpoints and Visual Studio's DataTable Visualizer I noticed that only calling TBL.Columns.Clear() left the empty rows still in the DataTable. Therefore, to answer the question of how to get rid of a column in a DataGridView that you don't know why/how is there, I suggest to call:
DataTable.Clear()
DataTable.Columns.Clear()
Before setting your DataGridView equal to your DataTable.
Taken from the MSDN:
The .Clear() Method of a DataTable Class "clears the DataTable of all data."
The DataTable.Columns Property gets "a DataColumnCollection that contains the collection of DataColumn objects for the table"
The DataColumnCollection Class also has a .Clear() Method which "clears the collection of any columns."
Thank you #TnTinMn for pointing me in the right direction by using breakpoints and #LarsTech for making me realize that I harshly mixed up DataGridView and DataTable in my original answer.
I hope this post can help others prevent themselves from ripping their hair out about where a non-existent column in their databases seemingly materialized from... If this does not fix your specific issue. I would also check the Query, Database Table setup, and the DataGridView; but for me the issue was with the DataTable.

Related

Filtering by ID column

I am trying to filter a table from Ms access DB in visual studio by ID (PID) column but I can't figure out how to convert int to string, or to make it work.
Any ideas please.
con.ConnectionString = dbProvider & dbSource
con.Open()
If PIDfindTextBox.Text = "" Then
MessageBox.Show("Please enter a Patient ID number")
Else
PatienrocordBindingSource.Filter = "((PID,'system.string') like '" & PIDfindTextBox.Text & "')"
If PatienrocordBindingSource.Count <> 0 Then
With dataGridView1.DataSource = PatienrocordBindingSource
End With
Else
MessageBox.Show("Searched Patient ID was not found")
PatienrocordBindingSource.Filter = Nothing
End If
End If
End Sub
Your code is very confused. It opens a database connection then sets a bindingsource filter, this isn't really how things go
A bindingsource is a device that sits between a model of data such as a datatable (which is not a table in a database) and a UI element such as a datagridview or other controls. The bindingsource can filter the data it finds in the model. None of this is anything to do with filling the model up with data in the first place, which often is done by pulling it out of a database
You can probably avoid interacting with a database connection entirely; if you use an OledbDataAdapter you can pull data out of your database and load it into a datatable in your program's memory
You thus have a choice of where to filter your data. You either load the entire database into your program's memory and then use bindingsource filter to show just the one if you want - all the data lives in the datatable and only some of it passes through the bindingsource ..
Or you only download some of the data out of the database and into the datatable, and then you don't need to filter it in the bindingsource
You can also take a hybrid approach of loading, say, 10 records into the datatable and then filtering In the bindingsource
Choose your scenario - most people opt for the middle one where you just download the data you need. There are plenty of examples out there but as a rough template, searching a database table by I'd and pulling the results would look like:
Dim da as New OleDbDataAdapter("SELECT * FROM Person WHERE Id =?", "connection string here")
da.SelectCommand.Parameters.AddWithValue("id", Convert.ToInt32(idTextbox.Text))
Dim dt as New DataTable
da.Fill(dt)
bindingsource.DataSource = dt
If you had 10 rows in your datatable and wanted to filter to just some one id
bindingsource.Filter = "[Id] = " & idFilterTextBox.Text
You don't need to use both of these approaches; use the one that is right for your context

How can i set the value from the last row in an specific column in a variable in VB.Net

I'm develop an application using forms in vb.net with visual studio 2019
I have code in the event click for one button
Dim oda As New OleDbDataAdapter
Dim ods As New DataSet
Dim consulta As String
Dim cadena As New OleDbConnection
Dim comando As New OleDbCommand
Try
cadena.Open()
comando = New OleDbCommand("Insert into QRQC (Nombre,NumControl,Fecha,Hora,Turno)" &
"values(txt_nombre,txt_numControl,lbl_fecha,lbl_hora,cBox_turno)", cadena)
consulta = "Select *From QRQC"
oda = New OleDbDataAdapter(consulta, cadena)
ods.Tables.Add("QRQC")
oda.Fill(ods.Tables("QRQC"))
Dim row As Integer
row = ods.Tables("QRQC").Rows.Count - 1
courrentId = ods.Tables("QRQC")(row)("ID_QRQC").ToString()
frm_newPt2.lbl_folioQRQC.Text = courrentId
cadena.Close()
Catch ex As Exception
MsgBox("Error al generar el registro en la base de datos", vbCritical, "Aviso")
Console.WriteLine(ex)
cadena.Close()
GoTo skip
End Try
Everything goes perfectly, but when I delete some record on my DB this part of the code always return the value 102
courrentId = ods.Tables("QRQC")(row)("ID_QRQC").ToString()
How can i solve this problem?
First of all, your insert command is wrong, and will not work.
You have "values(txt_nombre. etc etc."
But that is just a string and NOT the actual values from the form. So you are actually going to "instert txt_nombre" into that table and NOT the value of that label or text box on the form!!!
So you need to fix and get your insert command working FIRST.
And if this is just editing data then consider using the data binder, since navigation, editing, deleting and saving of data to/from the table can occur 100% automatic whiteout ANY code on your part.
so first up is to fix that insert command. You can't JUST use a string with the names of the controls else that would actually as noted try to insert the names of the controls as text and NOT the values of the controls.
And lets clean up a few other things. No need for a dataset, since a dataset is a SET of tables - we only dealing with one table (so use a data table).
But as noted, before we mess with data tables, we have to fix that insert command.
It will, can look like this:
Dim strSQL As String
strSQL = "Insert into QRQC (Nombre,NumControl,Fecha,Hora,Turno) " &
"VALUES(#nombre,#numControl,#fecha,#hora,#turno)"
Using cmdSQL As New OleDbCommand(strSQL,
New OleDbConnection(My.Settings.TestDB))
cmdSQL.Parameters.Add("#nombre", OleDbType.Integer).Value = txt_nombre.Text
cmdSQL.Parameters.Add("#numControl", OleDbType.Integer).Value = txt_numControl.Text
cmdSQL.Parameters.Add("#fecha", OleDbType.Integer).Value = lbl_fecha.Text
cmdSQL.Parameters.Add("#hora", OleDbType.Integer).Value = lbl_hora.Text
cmdSQL.Parameters.Add("#turno", OleDbType.Integer).Value = txt_nombre.Text
cmdSQL.Connection.Open()
cmdSQL.ExecuteNonQuery()
End Using
So you have to "replace" the string values in the sql with the ACTUAL values you are using.
You also don't show where/how you setup your connection to the database. I guessed that you used the applications settings and the connection builder - so you have to change TestDB to your actual connection that you used.
The above will thus get your insert command working.
At that point, you can post a new question in that after you do a insert, how to get the new autonumber primary key, or whatever else you wanted to do, but your insert statement as written will not work.
As noted, perhaps it better to use data bound controls. This will result in a Access like design experience, and you not having to write ANY code to edit a table in vb.net.
And it not clear if the control names I used are correct (or they are even controls on the form), but if they are, then ".Text" is required to grab the values. You have to of course change (check) that the control names I used and guessed are correct.
You also have to change the data type "integer" I used in above to the correct data types. For text I recommend you use .VarWChar

how to sorting item in combo box by Alphabet

i use this code to fill the search result records in combo pox and it working good ..
da = New SqlDataAdapter("Select * From MovTable where NameOfMov like '" & AlphaCB.Text & "%'", sqlcon)
da.Fill(dt0)
SearchResultCbB1.DataSource = dt0
SearchResultCbB1.ValueMember = "NameOfMov"
but i need some change to make the combo pox sorting them by Alphabet
thanks
When you attach a ComboBox's datasource to a datatable (dt0) it actually attaches to the .DefaultView DataView of the table. This means you can set the .Sort property of the view to sort the combo:
dt0.DefaultView.Sort = "[NameOfMov] ASC";
SearchResultCbB1.DisplayMember = "NameOfMov" 'this shows in the combo
SearchResultCbB1.ValueMember= "ID" 'you probably want an ID, not the movie name, for this
SearchResultCbB1.DataSource = dt0
You can change this Sort property at any time. For more info on what you can do with it, see the documentation
Please don't write SQL's like you have there; it's a massive security flaw. For more info on why, read http://bobby-tables.com - it will also give advice on how to prevent it, but really you should look at upgrading your knowledge to use Entity Framework or Dapper for your data access and never again, ever concatenate a value into an SQL string
Please always use parameters to avoid sql injection and make you your sql query strings easier to write. I had to guess the datatype and size of the parameter. Please check your database for the actual values and adjust the code.
The user interface is updated after the database objects are closed and disposed with the Using...End Using block.
Private Sub OPCode()
Dim dt0 As New DataTable
Using sqlcon As New SqlConnection("Your connection string"),
da As New SqlDataAdapter("Select * From MovTable where NameOfMov like #Name Order By NameOfMov;", sqlcon)
da.SelectCommand.Parameters.Add("#Name", SqlDbType.NVarChar, 400).Value = AlphaCB.Text & "%"
da.Fill(dt0)
End Using
SearchResultCbB1.DataSource = dt0
SearchResultCbB1.DisplayMember = "NameOfMov"
SearchResultCbB1.ValueMember = "MovieID" 'The Primary Key field in you Database
End Sub
this is an alternative right answer for my question
da = New SqlDataAdapter("Select * From MovTable where NameOfMov like '" & AlphaCB.Text & "%' order by NameOfMov ", sqlcon)
All I needed was this one addition "order by NameOfMov"
Didn't need all this hassle.

Delete a row through DataGridView

I have a Button that lists to me everything from a database and another Button that was made to delete something from database by "Name". To do that, I have a TextBox where I input the "Name" and delete it from the database.
To make things easy and faster I had another solution which is simpler than what I am currently doing. What I want it to do is click on a row and then press the delete Button and have the row be deleted from the database. I found this solution but this doesn't work:
For Each row As DataGridViewRow In myDataGrid.SelectedRows
myDataGrid.Rows.Remove(row)
Next
Basically what I have to do in the code is make a query and select the row that I want right?
My apologies I am not able to comment. In either case, if you are trying to delete the record from the database, you will have to use a delete query.
Below is an example on how to do it:
delete selected row from datagridview and datasource table
Without using a stored procedure you can use this code:
Dim cn As OleDbConnection
Dim cmd As OleDbCommand
Dim cnstring As String = "Your connection String"
Dim sqlstring As String = "Delete from yourTable where column= your record"
cn = New OleDbConnection(cnstring)
cmd = New OleDbCommand(sqlstring, cn)
cn.Open()
cmd.ExecuteNonQuery()
cn.Close()
The For[...]Next statement will only delete the DataGridViewRow from the DataGridView. It won't commit any changes to the database.
A DataGridView is a view of the data. You would need to commit the changes on the DataSet.
If you want a more specific answer post the code that shows how you are binding the data to the DataGridView.

Using TableAdapter to insert rows into a dataset does not do anything

I have a question similar to this one, but reading the (accepted) answer didn't give me much insight, so I'm hoping to state it more clearly and get a clearer response back.
I'm attempting to insert a data row into a table. I'm using TableAdapter's custom "insert nonQuery" that I wrote (it works, I tested) to accept some parameters. I'm fairly new to this business of communication with a database via .NET and what I'm doing is probably wrong by design. My questions are why is it wrong and what's the right way to do it? Both are equally important, IMO.
Here's some sample VB code I wrote:
Dim arraysTableAdapter As New UnitTestsDataSetTableAdapters.ArraysTableAdapter
Try
arraysTableAdapter.InsertArray("Test Array", 2, 1, 2, "Test user")
Catch ex As SqlException
MsgBox("Error occured when trying to add new array." _
& vbNewLine & vbNewLine _
& ex.Message)
End Try
...and that's pretty much it. There is no exception raised, my table does not get a new row inserted. Everything is just the way it was before I called the InsertArray method. When I test my query in the QueryBuilder with the same parameters, a new row gets added to the database.
Now, I do understand some of the reasons this would not work. I understand that I need to create and select a row in my DataSet (no idea how to do it) in order to tell the TableAdapter what it's adding the data to. Or at least I got that impression from reading the vast abyss of forums.
I would really like to use TableAdapter at some point, because it knows that .InsertArray exists and it knows which parameters it likes. I could try and do it using
Dim con As New SqlConnection
Dim cmd As New SqlCommand
con.ConnectionString = connString
con.Open()
cmd.CommandText = "INSERT ...... all that jazz"
but it's not nearly clean enough for how clean I like my code to be. So, is there any way to do what I'm trying to do the way I'm doing it? In other words, how do I use the neat structure of a TableAdapter to communicate to my DataSet and put a new row in it?
Thanks in advance!
There were two things that were wrong:
(minor issue) I did not have a DataTable filled from the TableAdapter (see code below)
(major, sneaky issue) My method worked from the very beginning. There is nothing extra to be added except for the line above. However, the ConnectionString of arraysTableAdapter was pointing my program (automatically, by default) to a wrong location. Once I manually set the ConnectionString, it worked perfectly.
Here's my complete code:
Dim connString As String = "Some correct connection string"
Dim arraysDataTable As New SpeakerTestsDataSet.ArraysDataTable
Dim arraysTableAdapter As New UnitTestsDataSetTableAdapters.ArraysTableAdapter
'Set the correct connection string'
arraysTableAdapter.Connection.ConnectionString = conn
'Fill table from the adapter'
arraysTableAdapter.Fill(arraysDataTable)
Try
arraysTableAdapter.Insert("Test", 2, 1, 2, Now, Now, "Me")
Catch ex As Exception
MsgBox("Error occured when trying to add new array." _
& vbNewLine & vbNewLine _
& ex.Message)
End Try
The accepted answer in the question you linked to is correct, but sometimes saying it in different words helps:
A TableAdapter is used to communicate between a DataTable (there can be one or more DataTables in a DataSet) and a database. It can pull data from a database and add it to a DataTable and it can send data from a DataTable to the database. It's purpose is to create and execute the SQL code required to make this communication work.
You are trying to use the TableAdapter to directly add data to your DataTable. This will not work. Instead, you should use the methods that come with the DataTable to add a new row to the DataTable and then (if necessary) use your TableAdapter to send that row to a database.
For instance, with a Dataset called DataSet1 that contains a DataTable called DataTable1 that has three text columns you can add a record like this:
Dim d As New DataSet1
d.DataTable1.AddDataTable1Row("value1", "value2", "value3")
That AddDataTable1Row method is automatically created for you, and I think is what you are looking for.