Delete selected rows in datagridview from database - sql

I'm trying to delete the rows which the user selects in a datagridview using SQL Server.
I have a datagridview that loads the contents of the database, in this case Username and Password.
Keep in mind that each username is unique in the database and so I should be able to delete each row using the unique username.
The SQL I currently have is DELETE FROM 'Users&Passwords' WHERE 'Username' = ? I'm not sure if this is entirely correct, however whenever I click QueryBuilder it seems to accept it.
The code I have to try and do this is as follows:
Private Sub btn_remove_Click(sender As Object, e As EventArgs) Handles btn_remove.Click
For Each row As DataGridViewRow In DataGridView1.SelectedRows
Dim usernametodelete As String = DataGridView1.SelectedRows(0).Cells(0).Value.ToString
'TextBox1.Text += usernametodelete
Me.Users_PasswordsTableAdapter.DeleteUser(usernametodelete)
Me.Users_PasswordsTableAdapter.Fill(Me.ManageUsersDataSet._Users_Passwords)
Next
End Sub
I would like that when the user clicks the Remove User(s) button the selected rows from the datagridview remove the rows from the database. Any help would be greatly appreciated.

You're getting slightly more involved than you need to. The set of steps you'd ideally take would be:
0) rename your table so it doesn't have an & character in it - it's just asking for trouble
1) Add your table to your dataset with something like this process: right click the design surface, new tableadapter, configure the connection string, set the query as SELECT * FROM Users WHERE Username LIKE #username, ensure other things are set, like whether you want generate dbdirect methods, and whether you want the dataset to refresh new values
2) In your data sources window (might not be showing by default, find it in on of visual studio's menus) drag and drop the Users node from the data soruces window, out onto the form. This will create a datagridview bound to the typed datatable, and also create a dataset, tableadapter, tableadaptermanager (not strictly needed; can delete), a bindingnavigator tool strip (again not strictly needed but has a handy pre-wired Save button on it) and a bindingsource. It will also pre-fill some code into the form_load event handler to fill the datatable
3) That's it - your form has a grid, bound to a datatable. That grid is capable of deleting rows - click the row header and press the delete button on the keyboard, row disappears. Click the save icon in the toolstrip, and the change is persisted to the database. The only thing you have to do is get data into the table in the first place. I gave a SQL that allows you to choose some usernames to load, but you can easily make it load the whole lot by changing the line of code in Form_Load to:
yourTableAdapterName.Fill(yourDatasetname.YourDatatableName, "%")
Passing a percent as the name is like a * wildcard in DOS. LIKE % will select all records. You can also, of course, leave the default provision (it will reference a textbox on the toolstrip) and instead run the program, put a % in the textbox on the toolstrip and click Fill. Or you can put JOHNSMITH, or JOHN% in th textbox and fill, to load that user/those users respectively
Hopefully you already did 1 and 2..
A bit of a background story on how all this stuff works:
DataTables are client side representations of tables in the database. It isn't intended that they contain all the data in the database, only a portion of this that you want to work with. When you load a row from the DB you can edit it, delete it (mark as deleted) and when you call tableAdapter.Update(yourtable) th changes you made are persisted to the DB. Note that even though it's called Update, the method will save new rows (by doing an INSERT), deleted rows (SQL DELETE) and make updates (SQL UPDATE). If your datatable has 4 rows laodd from the DB, and you then add 2 new rows, make changes to 3 of the loaded rows and delete the 4th row, then calling tableadapter.Update will save all these changes to the DB. You aren't required to pick through your datatable, calling tableadapter.insert/update/delete accordingly, to manually persist these changes. The flow of using a tableadapter is thus:
tableAdapter.Fill(datatable, maybe,parameters,to,control,the,fill,here)
'work with the datatable here, change, insert, delete. Use loops/code, use the UI, etc
tableAdapter.Update(datatable) 'save changes

I suggest putting an id column in your datagridview and just hide it so that you can easily delete the record you want to remove easily without conflict, because if you will use a username, what if theres a duplicate username exist.
Private Sub BTNDELETE_Click(sender As Object, e As EventArgs) Handles BTNDELETE.Click
Public result As Integer = 0
Public cmd As New MySqlCommand
strcon.Open() 'your connection string here
With cmd
.Connection = strcon 'your connection string
.CommandText = "DELETE FROM `users` WHERE `id` = '" & DTGLIST.CurrentRow.Cells(0).Value.ToString() & "';"
result = cmd.ExecuteNonQuery
If result > 0 Then
MsgBox("Successfully Removed.", MsgBoxStyle.Information, "Info")
DTGLIST.Rows.Remove(DTGLIST.SelectedRows(0))
End If
End With
strcon.Close() 'close the connection string
End Sub

Managed to figure out why my delete query wasn't working a few days ago. It was due to my SQL not being correct. This worked for me DELETE FROM [Users&Passwords] WHERE (Username = ?).
Also having the line Me.Users_PasswordsTableAdapter.DeleteUser(usernametodelete) in my code made it work.

Related

How to read an Access database column into an array with VB.NET?

There's already a question like this but its in VBA, and I need VB.NET
I'm trying to get the contents of a column then put them in an array or something so I can then put the data into the items of a ComboBox. If anyone can suggest a better way, id love to know. This is the code I am using right now:
sql = "SELECT Firstname FROM Candidates WHERE Position='President'"
cmd = New OleDbCommand(sql, cn)
dr = cmd.ExecuteReader
So, first lets build the connection to the Access DB.
So, from the menu go project -> "my project name" properties
(last option).
This:
So, in above we hit the [...] button (connection builder).
Then this:
and then:
then use browse to select the Access database file.
If this is a "mdb" file, then we use JET, but for accDB, we have to choose/use
ACE.
So, after selecting the access file, then hit advanced:
this:
Now, it should default to ACE, but MAKE SURE you check this!!!
This:
If you don't see "ACE" in that list, then you not be able to use/open a accDB file, but can use JET to open mdb files.
Keep in mind, that if you are using vs2022?
Then the test connection button will ALWAYS fail, but if you run your project/code, it should work.
Note that you ALSO MUST force your project to x86 if you using/have Access x32 bits.
So, that is this option:
If you don't have/see a x86 option, then use the configeration manager, and create a x86 choice. You MUST do this!!
Ok, so now we have our connection built.
So, on a form, lets drop in a button to "load" the combo box, drop in a combo box.
And lets even drop in a button to show how to get/grab/use a value the user selected.
Now, a combo box can (often) have two columns. one column is "hidden", and the other is for display.
So, in our example, we will fill out the combo box with a list of hotels from the database, and we will use both columns.
"id" - that is the database primary key value - it will be hidden, not display.
"HotelName" that is the column from the database to display in the combo box.
So, in the combo box property sheet, set:
ValueMember to ID
DisplayMember to HotelName (or your column to display).
So, the code for loading the combo box will look like this:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim strSQL As String =
"SELECT ID, HotelName FROM tblHotelsA ORDER BY HotelName"
cboHotels.DataSource = MyRst(strSQL)
End Sub
Function MyRst(strSQL As String) As DataTable
Dim rstData As New DataTable
Using conn As New OleDbConnection(My.Settings.AccessDB)
Using cmdSQL As New OleDbCommand(strSQL, conn)
conn.Open()
rstData.Load(cmdSQL.ExecuteReader)
End Using
End Using
Return rstData
End Function
And our button code to test get/grab/see the selected value is this:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Label2.Text = "Hotel Select = " & cboHotels.Text &
" value = " & cboHotels.SelectedValue
End Sub
Note how we are able to get the 2 values fro the combo box (the database primary key "value") and also the text (hotel name).
So, final result is this:

How do I make DataBindings update in runtime?

Noob programmer here, go easy on me if the answer was straight up obvious. Couldn't really find the right title but it's the closest one I got.
To get straight to the point, I have a textbox in my program, and whatever I type in the textbox should go straight to a table in my database, and then when I click a specific button, whatever I last put in the table should show up on the label beside the textbox via DataBindings (at least, that's how I want it to go).
It works for the most part. When I type something in and click my button, the text shows up on the label. But when I do it a second time , the label doesn't update to what I last typed (it only updates when I stop and start running the program again.)
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
connection.Open()
Dim test1 As String = "SELECT TOP 1 Letters From NewTable ORDER BY Id DESC"
ExecuteQuery(test1)
Dim command As New SqlCommand(test1, connection)
Dim adapter As New SqlDataAdapter(test1, connection)
adapter.Fill(TestDatabaseAgainDataSet1, "NewTable")
randomlabel.DataBindings.Clear()
randomlabel.DataBindings.Add("Text", TestDatabaseAgainDataSet1.NewTable, "Letters")
command.ExecuteNonQuery()
connection.Close()
End Sub
I know there are some easier ways for user-generated text to show up on a label, but I kinda need it so the last thing I typed is still there when I click the button.
If I understand correctly, you only have problem on the second part of your project: whatever you last put in the table should show up on the label beside the textbox.
If you are on SQL Server you can use SqlDataReader class that provides a way of reading a forward-only stream of rows from a SQL Server database.
Dim cmdLastLetter As SqlCommand = conn.CreateCommand()
cmdLastLetter.CommandText = "SELECT TOP 1 Letters From NewTable ORDER BY Id DESC"
Dim drLastLetter As SqlDataReader = cmdLastLetter.ExecuteReader()
If drLastLetter.Read() Then
Me.Label1.Text = drLastLetter("Letter")
End If
drLastLetter.Close()
cmdLastLetter.Dispose()
If you are using another database consult this document: you have to use another class but the concept is the same.

Anyway to Check if any datatable.Columns is added vb.net

I have a dataset with a datatable with Columns.
I fill dataset with this code in Winforms
myAdapter = New SqlDataAdapter("Select * from users", strSqlConn)
myAdapter.Fill(dsDataset, "Users")
dcPk(0) = dsDataset.Tables("Users").Columns("FirstName")
dcPk(1) = dsDataset.Tables("Users").Columns("LastName")
dsDataset.Tables("Users").PrimaryKey = dcPk
Is it anyway to check if any datatable.Columns is added vb.net? Later in code For example "amount" is added
dsDataset.Tables("Users").Columns.Add("amount", System.Type.GetType("System.Int32"))
What I really want - I have alot of datasets and I want to see if it any real changes in them (not added columns whois not part of the database) if not, dont save to database.
When I use GetChanges it says I have changes if I have added columns, but the added columns should be excluded.
Now I have hardcoded the added columns to exclude them in the check, it works but thats not a good way to maintain. Another way is to make a copy of all datasets and compare them, in the copy there is no added columns. But Im not sure about performance when its alot of datasets...
Like in rows
If row.RowState = DataRowState.Added Then
'Do something
end if
You should be able to use the GetChanges() method of the DataTable object, like so...
dim t as DataTable = MyDataTable.GetChanges()
If t IsNot Nothing then
' There were changes to the table
Else
' There were no changes to the table
End If
Please be sure to read the documentation page that I linked to be sure that it meets your requirements.

How to run code in real time across multiple tabs, windows form, vb.net

I am currently programming in vb.net for a windows forms applications.
I have a windows form with multiple tabs and within each tab I have a DGV. Each DGV is connected to an sql server table, the same table across all tabs.
I want to use a check box to copy rows of data from the sql table to a specific tab. In this case I want to try and have this happen in real time, so without using a "refresh" button or something like that.
On each row in every tab I want the row of data to appear or disappear from the last tab depending on the status of the check box.
I have attached code and a picture. The code is used on the form load event to load the tables into the tabs. In the image you can see i want the rows to be loaded into the "ordered floors" tab after the check box has been checked.
Private Sub FormOrdered_Load(sender As Object, e As EventArgs) Handles Me.Load
'load line 2 tab
Try
Using conn1 As New SqlConnection(connstring)
conn1.Open()
Using comm1 As SqlCommand = New SqlCommand("Select LineNumber, ShearNumber, JobNumber, FloorNumber, OrderedBy, DateOrdered, Ordered FROM Production.dbo.tblFCordered where LineNumber = 2", conn1)
Dim da As New SqlDataAdapter
da.SelectCommand = comm1
da.Fill(Line2)
End Using
conn1.Close()
End Using
DataGridLine2.DataSource = Line2
Catch ex As Exception
MsgBox("Unable to make SQL Connection to load Line 2 Table, please contact an engineer!")
MsgBox(ex.ToString)
End Try
image
You could just clone the rows from the DGV when you check the checkbox and add them to the Ordered floors dgv.
Something like:
Private Sub CopyRows_CheckedChanged() Handles CopyRows.CheckedChanged
For each r as DataGridViewRow in MyDGV.Rows
dgvOrderedFloors.Rows.Add(r.Clone())
next
End Sub
You'll have to modify this to suit obviously, but I think something along these lines should do what you want.
Or you could clone the data tables you use for each datagridview, and add them to one master table which will be the datasource for your Ordered floors datagridview.
That would be better, but might be more work upfront.

Trying to copy a datagridview from one form to another

I know my title is a little strange. Let me explain. I am trying to "merge" two databases, one we house locally and one that is at another facility with the hopes of avoiding our admin group having to duplicate entry through separate forms. I have the source for a webservice that connects to the offsite database and I can enter data. What I am trying to do is expand that source by adding in our own database and copying our data to theirs. Hope this makes sense.
Anyway,
So both the local and offsite forms have datagridviews attached to them. I can currently copy the contents of the first row to their form for entry, but I am getting errors when it attempts to go to the second row. Here is my code:
Dim i As Integer
For i = 0 To VRMAdDataGridView.Rows.Count - 1
'For Each row As DataGridViewRow In VRMAdDataGridView.Rows
'myrow = VRMAdDataGridView.CurrentRow.Index
frmcall.dgvRMAItems.Rows(i).Cells("cItemID").Value = Me.VRMAdDataGridView.Rows(i).Cells("DataGridViewTextBoxColumn5").Value
frmcall.dgvRMAItems.Rows(i).Cells("cExpectedSerialNumber").Value = Me.VRMAdDataGridView.Rows(i).Cells("DataGridViewTextBoxColumn2").Value
frmcall.dgvRMAItems.Rows(i).Cells("cNotes").Value = Me.VRMAdDataGridView.Rows(i).Cells("DataGridViewTextBoxColumn3").Value
'Format Type codes from FW to match Utica
Select Case Me.VRMAdDataGridView.Rows(i).Cells("DataGridViewTextBoxColumn6").Value
Case "Repair"
frmcall.dgvRMAItems.Rows(i).Cells("cRequestedAction").Value = "Repair"
Case "RTS"
frmcall.dgvRMAItems.Rows(i).Cells("cRequestedAction").Value = "Rtn/Stock"
Case "Repair !!RUSH!!"
frmcall.dgvRMAItems.Rows(i).Cells("cRequestedAction").Value = "Rush Repair"
End Select
' myrowval = row.Cells("DataGridViewTextBoxColumn5").Value
' MsgBox(myrowval, MsgBoxStyle.Information, "Prod_Code")
'Do Something
Next
When I try to run the code I receive the following error:
{"Index was out of range. Must be non-negative and less than the size of the collection.
Parameter name: index"}
You should manipulate the underlying datasources, not UI elements (DataGridViews in this case). For example, your DataSource is a DataTable. Then just use Clone method to get a copy. Then set a DataSource of that other DataGridView. If you need something more than a copy, it's definitely going to be more simple to work with a series of DataRow objects.