One idea
If you are simply using a single DataSet, you can statically store the
DataSet and run updates on it. You then rebind the DataGrid when you alter
the record outside of the DataGrid. With this idea, you can do both types of
edits. It also gives you some control of when you send the data back to the
database. The downside is you have taken over some of the automatic control
that ADO.NET offers. The danger here is if the dialog is not modal and the
user can edit in both places at the same time.
NOTE: If the app is connected all the time, there is little danger in
forcing the data back to a database when anything is changed and refreshing
the DataSet. This makes the app chattier, but this is not often a problem on
an Intranet, unless you are downloading tons of data at one time (not a wise
idea if not needed).
--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA
***************************
Think Outside the Box!
***************************
"Massimo" wrote:
> I have a Windows Forms applications with a SQL Server back-end.
>
> There is a main form which shows a list of selected columns from a table
> (all rows are to be shown), and a dialog form which opens a detailed view of
> the selected record in the list and lets the user modify it; I'd also like
> to use the same dialog to add a new record, without rewriting the same code
> twice.
>
> The question is: what is the proper way to handle this?
>
> Possible solutions I've devised:
>
> 1) Using a query (SqlReader or DataSet + TableAdapter) to populate the list
> with all the needed data, then using the selected item index to get the
> table ID for the record; then passing the ID to the dialog form, which will
> create and populate an internal DataSet and act upon it; upon clicking "OK",
> it will save the modified DataSet to the DB (if any modifications were
> made). A special ID value (-1 ?) will be used to mean "create a new record
> and save it if the user clicks "OK". The DataSet will be discarded as soon
> as the dialog form closes.
>
> 2) Same as 1), but the DataSet will be populated inside the main form and
> passed to the dialog form; the form will modify it (eventually), and return
> it back to the main form, wich will save it or reject it based on
> DialogResult. This approach lets me populate it with a new row and pass it
> to the dialog, so there is no need to handle special cases in the dialog
> form. The DataSet will be created, filled and then discarded each time.
>
> Both of these approaches work on single rows of data, which are to be
> extracted from the DB upon request; but the whole amount of data will be
> relatively small (one or two hundreds of records, at most), so I thought it
> could also make sense to fully read it, put it in a DataSet and work with
> it, saving modifications when they're made; so, here's approach 3:
>
> 3) Fill a DataSet with all the data, including detailed data not shown on
> the main form; manually build the main list with the required info (which is
> to be built manually anyway, since some columns are to be grouped into text
> rows) and use it to select the row to modify; upon clicking the "Modify"
> button, pass the DataSet object and the row ID (which is easy to obtain
> since the whole table is available in the DataSet) to the dialog form; when
> clicking "New" instead of "Modify", add a new row to the DataSet and pass
> its ID to the form. When the user clicks "OK", save the data back to the DB
> and do a DataSet.AcceptChanges(); otherwise, if "Cancel" is clicked, do a
> DataSet.RejectChanges().
>
> This seems to be the better approach, but there are some points I don't
> quite understand.
>
> First: I can't do AcceptChanges() or RejectChanges() inside the dialog form,
> since the main form would be unable to know if rows where modified; so, I
> must either save the changes inside the dialog form (which I don't want to
> do, since DB update logic doesn't belong there as in #1) or have the main
> form guess what happened using DialogResult; this last one seems OK, but is
> this good OO practice? The form receives a DataSet, shouldn't it be its
> responsibility to modify it or leave it untouched? Can I solve this using
> EndEdit() or CancelEdit() on the single row?
> Second: what happens if the user clicks "New" and then decides he doesn't
> want to add a new record and clicks "Cancel"? Will RejectChanges() delete
> the new row, or should I manually handle this? More generally: will
> RejectChanges leave the DataSet exactly as it was when the last
> AcceptChanges() was called?
>
>
> Side question: I have to use the same approach (main form with summary data,
> dialog form with detailed data) in some other parts of the application;
> again, the whole database will be quite small (maybe five tables, at most
> one-two hundred records each, plus some smaller ones (10-20 records)); also,
> some of these tables are linked with relations, which I'd like the program
> to enforce before trying to update the DB. Will it be a good design to put
> all of the tables into one big DataSet, fill it and use it as in #3? What is
> the practical limit for using a single DataSet, and when is it better to
> partially fill small ones with ad hoc queries?
>
>
> Thanks for any suggestion.
>
>
> Massimo
>
>
> P.S.
> I'm using Visual Studio 2005 beta with SQL 2005, so the framework version is
> 2.0; I don't think this should be of any relevance to this design question,
> but if the new framework offers better approaches than the other ones, feel
> free to let me know :-)
>
>