Data Adapter does not update all rows updated - vb.net

So long story short I have a dgv that gets data from a mysql database and I can make changes to the data in the grid and save back to the table, no problem except this: Changes made by the user on the dgv are not done directly (or manually) on the dgv, rather the user clicks plus or minus buttons and I pragmatically increase or decrease the number in a certain field called Quantity which is actually the only field that can be updated.
Now when I update my adapte command (...da.Update(ds, "salesDet")), the row I changed last does not get updated unless I manually leave that row to another row before pressing the update button. So for instance if I have 3 rows in the dgv and I select row 2 which has a quantity of 1, then I press the plus button, the quantity changes to 2. Then if I immediately press my update button while still on row 2, it will not get updated to my database. It will only work if prior to pressing the update button I leave row 2 to say row 1 or 3. Kind of like because I'm changing the numbers programmatically and not manually, I need to leave the edited row for an "after-update" commitment of the new values to fire? Don't know if I'm making sense but I'm really lost
I have tried dgv.EndEdit(), dgv.RefreshEdit(), dgv.Refresh() before updating but none of that works.
Thanks for your help

Sounds like the current row hasn't been validated yet, so your change has not taken effect. A clumsy hacky way of getting round this might be to set dgv.CurrentRow to nothing at the start of your Update method to force validation.

Related

vb.net dataview grid won't add record and doesn't update after data is modified independently

I have a dataview grid bound to a datasource at run time. The datasource is filled from an access database via a DataAdapter. The data fills and displays correctly, and updates to existing rows seem to work OK but I have two problems:
When I type something in a new row and then press return or switch to a different row, I want the DataAdapter to add that row then and there to the database so I can retrieve the Autonumber index of the new record from Access and use that to add an associated record in a different table (Entries, a many to many linking table). This isn't happening. In the RowLeave event I have adapter.Update(dsSentences) and then I check for the new row, but the RowCount doesn't reflect its presence even though the newly added data is visible in the grid, and the adapter.Update doesn't seem to have triggered the Insert query that I specified in the DataAdapter. So nothing is added.
(edit: OK, so the new row has not yet been added when this event is fired. Which event should I then use to commit the data and retrieve the Autonumber primary key for my new record? I've tried UserAddedRow but that one fires before you've entered any data into the new row.)
THe second problem is that I need to update the data independently and then have the grid reflect those changes. How do I do that? Is there some call that will force the grid to get the updated data from the DataAdapter via the Dataset? Any help would be much appreciated. I'm almost ready to dtop the whole idea of binding data and do it all through code, Data binfing is supposed to save time but I'm finding it labyrinthine and unpredictable.
FWIW here's the query I'm using to fill the grid:
PARAMETERS nIdCollection Long;
SELECT tblSentences.IdSentence, tblSentences.SentenceText, tblSentences.SentenceParsed, Not IsNull([tblSentences]![SentenceParsed]) AS HasParsed, Entries.IdEntry
FROM tblSentences INNER JOIN Entries ON tblSentences.IdSentence = Entries.IdSentence
WHERE (((Entries.IdCollection)=[nIdCollection]))
ORDER BY Entries.SortValue;
As you can see, it requires a record in Entries. After I've entered a new record in tblSentences, before there are any entries the IdEntry will be null assuming it shows up at all. That's why I need to intercept directly after the Insert, add the record to Entries and requery to keep everything in order. You could do it all in an SQL stored procedure but I have to use Access.
Edit: After a lot of googling I've come to the conclusion that what I'm trying to do = add a record to a table through an additional INSERT query apart from the one handled by the DataAdapter, every time a new row is added - simply can't be done if you are using data binding. I am going to have to delete all my code and start from scratch populating the grid through code (unbound). I think it's the only way to do what I want. I will leave this here as a warning to anyone else not to make my mistake of trying to use Data binding when your data is coming from more than one table. Bad mistake.

DataGridView bound to MS Access table with Autonumber Primary key causes Concurrency errors

A have a volunteer timesheet data entry system which allows the volunteers to enter the times they have spent on various activities. I used the VB.net Designer to create the system (OK, I know now that that was not a good move!) so please don't ask me to show my code, most of it is generated by the Designer. My problem is this:
Each new record is assigned a negative number as a primary key when it is entered which is the way a dgv works with Access Automumber keys. I am executing the following statements in the RowValidating event when the row is valid.
a_dgv.EndEdit()
a_dgv.CommitEdit(DataGridViewDataErrorContexts.Commit)
Me.TimeSheets2BindingSource.EndEdit()
Me.TableAdapterManager.UpdateAll(Me.MembershipDataSet)
This code does not update the primary key value on the dgv although it does so in the Access table. If a user then attempts to delete or alter a record he has earlier added in the same session the update fails with a concurrency error. The only answer if have found to this problem is to refill the whole table. This is obviously not a desirable solution. Does anyone have a proven tested one?
I should probably mention that my table has two databound comboboxes
I was under the impression that a datagrid that is the result of a dataset from say Access does not show the PK values as -1, -2, -3.
If you created the disconnected dataset (or datatable) in code from a fill (pull data from Access), then each row normally does not show the PK.
However, regardless of the above, assuming you entered 5 rows, and now need to see the PK values?
You will during data entry in the grid should see this:
In above, I have added two rows. Your save code is somewhat like this:
tblHotels = DataGridView1.DataSource
rstDataReader.Update(tblHotels)
tblHotels.AcceptChanges()
That will send the data back to SQL server (or Access), and the autonumber PK 'ids are then generated. However, such changes are NOT pulled back into the dataset/datatable. In other words, the PK id's are generated in the database, but UNLESS you re-pull the data, you are not going to see the PK values.
You WILL have to re-pull the data. However, you can keep the current position of the grid, and re-fill the data like this:
rstDataReader.Update(tblHotels)
tblHotels.AcceptChanges()
Dim MyTop As Integer = DataGridView1.FirstDisplayedScrollingRowIndex
tblHotels.Clear()
rstDataReader.Fill(tblHotels)
DataGridView1.FirstDisplayedScrollingRowIndex = MyTop
And then you should see this:
The other way would be to send + update each row as you edit data, and then pull the PK, but obvious then you not be able to update the all your grid changes with a SAVE button, and thus of course no un-do ability.
I find the above that re-positions the top of the grid does not flicker. On the other hand, I suppose this could/would depend on how large the data set is (but then again, loading up a grid with too many rows is less then ideal).
So, as far as I can tell, you have to re-pull the dataset/datatable to get the new generated PK id's, or you have to save + pull for each row you edit. For a gridview with even several 100 rows, I don't see any flicker with the above code.

update database when user add a row in datagridview

I'm having an issue with using a datagridview for a user entering data that's saved to a database. Basically, I just want them to throw stuff into a row and then my code will insert the data.
I tried LeavingRow event, but the problem with this is,enter the values in default row that is already added in datagridview, these value hasn't updated when this event triggers.
I also tried UserAddsRow, but had that fail because it triggers as soon as the user starts typing to add a row.
In Row leave event Use the following code before savig. Then try to save. While saving also you see the index of the row which your code is pointing.
yourgrid.CommitEdit(DataGridViewDataErrorContexts.Commit);
This code may help you..

Linking index of two or more listboxes in VB.NET

I'm doing an project and there is an requirment that i haven't come up with the solution yet.
I'm asked to create a result storing system for a long jump competion. I have to create three listboxes to store attempt numbers, results (in metters) and the corresponding points to each results. However, i can only give them one textbox to enter the results, attempt numbers and points must be calculated automatically and each athlete must have 4 results.
There are two things i would like to ask you guys:
If the user has entered something wrong, he/she should be allowed to delete one or all results. And when a result is deleted, all attempt number and point related to that result should be deleted as well. Clearing all is fine with me but only delete one from the list is not really. So how can i solve this problem.
The listbox containing attempt numbers should be in order (1, 2, 3, and 4). I can make the listbox to generate those numbers if the user enters all results in numerical order. HOwever, the problem is that he/she can delete ramdomly selected item. If he/she deleted attempt number 3 for instance, the next result added should have the attempt 3 back instead of attempt 5. And the new added result should move to position between 2 and 4 rather staying at the bottom.
I hope you can understand what i'm trying to say. Sorry about my explaination, English is not my native language.
All of your ansers are appreciated
You could select the item to delete with the listbox, and then remove as Farhan Sabir has said. You could then force the user to re-enter the distance for the attempt they have just deleted as the next value.
If you only have one textbox to enter the results, you could use a label to indicate which attempt they are entering (set it to automatically change to the number of items in the list +1 after entering a ditance). This would Indicate to the user that they have to re-enter a deleted distance straight after they have deleted one. A messagebox could help prompt this as well.
I am not sure how you would change competitor, but you have not mentioned that at all within your question.
something like this ?
ListBox1.Items.Remove(ListBox1.SelectedItem)
I think when you got the index of the selected item (as Farhan Sabir suggestion above), you can delete the item of the other 2 listbox base on that index. Then you may try the listbox1.Items.Insert to insert the item to specific index of the listbox. however, i think you would have to ask the user the input of the attempt number along with the attempt result in order to add it back to the list with right order

App is sending an email to the wrong person, anyone knows why or how to resolve?

I am still having some issues with the issue I posted last time regardin formview not updating correctly.
I have managed to narraow the problem to one sub below:
My issue appears to be on this line:
tbl.Rows.AddAt(tbl.Rows.Count - 1, row)
Anytime I attempt to update a row, only the first row gets updated. Subsequent rows don't get updated. Instead, when I click "Update", the cursor moves down to the next record without updating it.
When I commented out this
tbl.Rows.AddAt(tbl.Rows.Count - 1, row), I can now update each and every row.
After updating the row, an email goes out to the individual advising him/her about the update s/he just made. The problem is that email is getting sent to the wrong person and that's because of that one line that I just commented out.
When you are updating via tbl.Rows.AddAt, you are only updating the grid HTML, not the database. You need to make your changes to the underlying data source which is bound to the grid, and then possibly will need to re-DataBind the grid so that it sees the updated data source.