Question

I'm working with a SqlDataAdapter on a Windows Form with C#. I have a BindingSource linking it to my fields with functional record traversal and saving changes back to the database.

I'd like to give users the option of updating the database with changes to the current record, not writing those made to other records but keeping them in the set of cached modifications (i.e. Save vs. Save All).

I've put together the following which works (sort of):

SqlCommand updateCurrent = new SqlCommand("UPDATE Table SET Attribute = @attribute WHERE ID = @currentRecord", sqlConnection)

updateCurrent.Parameters.AddWithValue("@currentRecord", bindingSource.GetItemProperties(null)["ID"].GetValue(bindingSource.Current));
updateCurrent.Parameters.AddWithValue("@attribute", bindingSource.GetItemProperties(null)["Attribute"].GetValue(bindingSource.Current));

updateCurrent.ExecuteNonQuery();

It works in that it updates the currently shown record (and only that record), but when the regular update function is called later on, it causes a System.Data.DBConcurrencyException (UpdateCommand affected 0 of the expected 1 records).

I think I understand why the error is happening (I've made changes to the database that now aren't reflected in the cached copy), but not how to proceed.

Is there a best practice for doing this? Is it an inherently bad idea to start out with?

Was it helpful?

Solution

All you need to do in order to archive what you want is the following:

This command will update your database with the content of this particular row (yourDataRow).

YourTableAdapter.Update(yourDataRow);

This command will update the whole DataTable.

YourTableAdapter.Update(yourDataTable);

The DataTable will know which row have been updated and which have been saved.

OTHER TIPS

Just spit balling here after Taking A Look At It. But:

Problem #1 I would do it as such: If you're saving the updates as they happen, then the idea of a "Save All" is pretty much thrown out the window (useless) because saving all is obviously inefficient when everything is already up to date. ...So update one at a time OR require a SAVE ALL.

Problem #2 (actual complained about problem) The DBConcurrencyException is not an error, it's a thrown Exception (difference), and the only reason it's thrown is because there were no updates made to the database. (Because you are saving on a row basis already) Thus why would you have an update? You wouldn't. So perhaps an empty try/catch would be the best route since you seem to be auto-saving pretty much.

The Way I Would do it (honestly): Unless you're working w/ large amounts of data (lets say > 10,000 rows) I would create a "Save All" function which updates all rows that were changed (maybe use a focus listeners and add it to a list or something to figure out the change). If you wanted to save each time an edit was made like you are doing then use the "Save All" function , which in this case is just that 1 row. If others were changed, Save All to the rescue. Works each way.

Added Bonus: Using a cached copy is actually a dumb idea. (unless your computer is a beast) like I said for small data, totally fine. But let's image an 1,000,000 row database. Now try caching 1,000,000 rows... no you're right comparing will be faster, but loading all that unneeded data into memory is a horrible idea. You're program will crash when scaling.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top