How to tell if a UltragridRow is added (new) or just modified? - vb.net

I have an Infragistics Ultragrid on a winform. How can I tell if a row is added or just modified? The DataChanged property will just tell me if Data has changed, not if it was added (so I can put the row data in an SQL Insert statment) or if it was modified (so I can put it in an UPDATE sql statement.)
For Each row As UltraGridRow In GroupMetadataGrid.Rows
If row.DataChanged Then
Debug.WriteLine("Saving Changed Row")
End If
Next
Thanks in advance.

UltraGrid does not track if the row has changed or was added. Look at the answer from Mike Saltzman in this thread in their forum.
This is his answer:
The grid does not track this. If you edit a row in the grid and move to another row, all changes in the previous row are committed to the data source.
The grid doesn't deal with the data base directly, it only deals with it's local data source. So if you are looking to track changes in the data source that need to be written to the database, then the data source needs to take care of that. The DataSet and DataTable class have built-in support for tracking pending changes.
The only thing you might have to be concerned about with the grid is that the current ActiveRow in the grid may have pending changes that need to be written to it's DataSource. For this you can use DataChanged. The grid will automatically commit changes when it loses focus, but if you need to manually force the changes to be committed, you can use the grid.UpdateData method, or the Update method on any individual row.

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.

Saving a datatable back to the database in vb.net and sqlite

I have a datatable called DTAllCustomers which I update on a record by record basis, however I now need to change one field in nearly all records of the datatable. I want to quickly update the database with the updated info in the datatable.
I have tried:
Dim objCmdBuilder As New SQLiteCommandBuilder(AllCustomersAdapter)
DTAllCustomers.AcceptChanges()
AllCustomersAdapter.UpdateCommand = objCmdBuilder.GetUpdateCommand()
AllCustomersAdapter.Update(DTAllCustomers)
Each command is processed, however the underlying database is not altered?
I have searched for some time but can't find what I am doing wrong.
Any help is greatly appreciated
Brad
The issue is the fact that you are calling AcceptChanges. Once you have accepted the changes, there are no more changes, so what is Update going to save? That Update method already calls AcceptChanges implicitly once it has saved those changes to the database. It's very rare that you will have to call AcceptChanges explicitly. Here are some scenarios where you might manipulate the accepting of changes.
When you call Fill on a data adapter, the method will internally add a bunch of DataRows to the DataTable. In that case, the RowState of each will be Added, just like when you add a row yourself. That's generally not what you want when retrieving data though, so Fill implicitly calls AcceptChanges by default. Let's say that you want to retrieve data from one database and insert it into another. In that case, you do want all the rows to be Added. To do that, you set the AcceptChangesDuringFill property of the data adapter to False.
You have a single DataTable containing changes that you want to save to two different database tables. In that case, you would need two different data adapters. You would need the first Updte call to not accept the changes so they are still available to the second data adapter. In that case, you set the AcceptChangesDuringUpdate property of the first data adapter to False and the changes remain after calling Update. You might allow AcceptChanges to be called implicitly by the second data adapter or you might set AcceptChangesDuringUpdate on it too and then call AcceptChanges explicitly.
You have two DataTables in a parent/child relationship and you want to save changes from both to the database. In that case, you need to save child deletes before parent deletes and save parent inserts before child inserts. To do that, you would call GetChanges on the DataTables to get subsets to save in the appropriate order. Because you're not passing the original DataTables to Update, their changes won't be accepted implicitly, so you need to call AcceptChanges explicitly on each DataTable after a successful save.

VB.net DataRow.RowState will not update

I promise I've looked at the bazillion posts claiming this same issue, so please forgive me that I am still stumped.
I have a VS2008 smart device project containing a strongly-typed dataset. The user is allowed to input values and save them, each time creating a new record in the dataset. Should the user wish to edit values, a modal child form is displayed with several combo boxes containing the possible values for acceptable input to edit the row. Each combo box is bound in the constructor for the child form in the fashion below:
With cmbSize
.DataSource = frmMain.dstConfig.Sizes
.DisplayMember = "Display"
.ValueMember = "Value"
.DataBindings.Add("SelectedValue", trowNewRow, "SIZE", True, DataSourceUpdateMode.OnPropertyChanged)
End With
dstConfig is a dataset of tables containing the constraints. Binding to the source's display and value members works fine.
trowNewRow is a reference to the row in the dataset conveyed from the main form when the user initiates an edit procedure, to the child form by passing the row as a parameter "ByRef". The strong-typing is preserved. It occurred to me there may be some sort of a disconnection that I am not aware of when this occurs. I pass the reference by performing a "Select" procedure on the dataset and filtering by a unique ID field corresponding to the row that is to be edited. The result is a single-item array of strongly-typed rows of the same schema as the dataset's from which I pass the first (and only) item as my object.
After the user submits the changes by clicking an OK button, a procedure is triggered to evaluate whether or not a change was actually performed. The best way I thought to do this was by checking the RowState of trowNewRow. The RowState, however, remains "Added" regardless of the changes. Manually checking the values of the row indicates the changes have indeed been recorded. I've verified the AcceptChanges procedure of trowNewRow is not explicitly being called by any of my code.
I have tried the following:
1.) Calling the EndEdit procedure of trowNewRow
2.) Manually performing a WriteValue on the combo boxes
3.) Calling the EndCurrentEdit procedure on the combo boxes' BindingManagerBase objects
4.)Every combination of the above
Thank you in advance for any ideas or solutions.
A DataRow contains two sets of data - original and current - and the RowState reflects the relationship between them. If there is no original data but there is current data then the RowState is Added. As #Plutonix says, no amount of editing the current data is going to add original data so the RowState remains Added even if you make further changes. If there is no current data but there is original data then the RowState is Deleted. If the current data matches the original data then the RowState is Unchanged, otherwise it's Modified.
When you call Update on a data adapter or table adapter, the InsertCommand is executed for each Added row, the UpdateCommand is executed for each Modified row and the DeleteCommand is executed for each Deleted row. After a successful save, the adapter implicitly calls AcceptChanges. That will remove all Deleted rows from the DataTable and copy the current values in Added and Modified rows over the original values, changing the RowState to Unchanged.
So, the RowState is for tracking changes since the last save to the database. You can't use it to determine whether the user has made any changes in the UI unless you are saving those changes to the database after every edit. If you want finer-grained change-tracking then you have to implement it yourself. Personally, I don't bind in those cases but wait until the user clicks OK to push the data into the DataRow. That also allows you to cancel the latest edit without losing prior edits.

Data Adapter does not update all rows updated

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.

How to automatically retrieve data when new data detected and show on datagridview?

Currently I have a public retrieve class, and a timer to execute this retrieve class every 3 seconds. But I realized that there is a problem when more and more data comes in. I cannot drag up or down when I'm trying to view each row because every 3 second it continuously retrieve data from table and the datagridview keep repopulate.
(window form)
I got another solution and just wanted to ask expert(s) or guru(s) whether it is workable or not? Or maybe some one can guide me to another solution?
My second solution:
1. Retrieve count() [current rows in table] and paste it to label.
2. Use data reader to read the count() table every 3 seconds, if has row then perform no action, if has row = false then execute retrieve class.
Have you tried Data Binding your data to your visual elements? Also here. This would be the standard approach for hooking up your UI layer and backend, and is event driven rather than requiring, for example, polling.