2

I am making a app in Delphi 6 + MySQL database using standard data-aware components and dbExpress. The app allows a users to view records in a grid and edit data (insert and/or delete records) client side. These data edits are then only written to database on clicking the submit button. All of this works fine and has the following setup:

Controls: 1. DBGrid1 linked to a DataSource1 to display data visually. 2. DataSource1 is linked to ClientDataSet1 to offer data for DBGrid to display. 3. ClientDataSet1 is linked to DataSetProvider1 to provide client-side data for editing. 4. DataSetProvider1 is linked SQLDataSet1 which selects records from a single DB table. 5. SQLDataSet1 is linked to SQLConnection to provide connection to MySQL database.

Actions: 1. User inserts a record: I use ClientDataSet1.InsertRecord; 2. User deletes a record: I use ClientDataSet.Delete; 3. User submits data: I use ClientDataSet1.ApplyUpdates(-1);

This all works great in terms of handling data & posting data (with the inclusions of a small hack on DataSetProvider1BeforeUpdateRecord to delete records).

NOW FOR MY PROBLEM: When the user first loads the form, the DBGrid1 displays all original records, removes all deleted records. But when the user inserts a new record in ClientDataSet1, a blank record is displayed in DBGrid1. The actual data is not lost or set as NULLS as when you ClientDataSet1.ApplyUpdates, this record is correctly written to the DB.

I know TClientDataSet has a data property for original data and a Delta property for edited data. Can these two properties with data by displayed in a single DBGrid at one time & still allowing the user to edit the data?

I have looked at 30+ resources and demo apps & all avoid this issue. Can this be done?

Forer
  • 1,045
  • 1
  • 9
  • 32
  • 1
    Why is it a problem for a blank record to appear when you insert a new record? Isn't that just the blank record for you to fill in? – LachlanG Nov 01 '10 at 19:46
  • Nope. I run ClientDataSet1.InsertRecord([array of field values]); InsertRecord executes Insert then Post events. Once doing this, the DBGrid shows a blank record that is not editable. I execute ApplyUpdates to submit to DB and then query the DB Table and the newly inserted record is there. The problem is that the DBGrid is not displaying the field values in the newly inserted record. – Forer Nov 02 '10 at 06:15

3 Answers3

3

Ok...this question has been viewed a fair amount without much feedback. I did some research by downloading many tutorials, demo apps & read multiple articles/help info discussing the use of these controls.

The net result:

  1. These controls are a bit buggy in general.
  2. In specific reference to my question, it is safe to say the controls cannot do what I describe as a standard.

This is based on the 30+ demo apps, articles and tutorials I reviewed that either don't describe displaying both the original data with Delta data in a single data grid. Sure you could hack this outcome (which is what I did) using a Listbox or StringGrid, but that also indicates the control cannot or not usable at providing this functionality (on the slim chance it might).

This functionality is an obvious oversight in my opinion as a user wants to see the potential outcome of their actions, conveniently in a single data grid AND a developer wants to provide that in a simple & pain free way i.e. using a datagrid to display data!

Question Answered [if you can prove differently with a demo app that I want to review, I will remove this].

If you created a demo app and couldn't get it to work, up vote my answer. Thanks

Forer
  • 1,045
  • 1
  • 9
  • 32
  • There you go. Please check out my answer. – Marcus Adams Oct 20 '11 at 17:55
  • @Idsandon: Yup, its old. All developers need to use the tools available or provided to the project (sometimes old, sometimes bleeding edge). The solution is not to just update (that means money and often introdcues other issues). So the age of the version is immaterial to my project getting a solution, but will help others understand the context of the problem. Thank you fo ryour input – Forer Oct 24 '11 at 08:14
  • Yes, but it can be also hard to help on such versions, as most moved to later ones. Did you also applied all available update packs? Delphi 6 was a bit buggy when released. –  Oct 24 '11 at 08:56
  • I hear you. But D6 is what it is and updates are in place. The controls are just buggy or rather were a work in progress. A jump to even D7 or later would mean many changes on an app that is sure to be "put down" soon. Hopefully. – Forer Oct 24 '11 at 10:25
1

The TDBGrid control provided with Delphi does not have the built-in functionality to display both the old and new values for fields. You are welcome, of course, to inherit from the Grid or create your own and add the functionality, or buy a third party component that accomplishes what you want. You are not limited to the standard controls, though they do provide the most commonly required functions.

You can also accomplish what you want by using calculated fields. For example, if you have a String field Name, add a new calculated String field to the dataset called OldName, with the same length as Name.

Then in your OnCalcFields event for the dataset, simply enter code like the following:

if DataSet.State = dsEdit then
begin
  DataSet.FieldByName('OldName').Value := DataSet.FieldByName('Name').OldValue;
end
else
begin
  DataSet.FieldByName('OldName').Value := Null;
end;
Marcus Adams
  • 53,009
  • 9
  • 91
  • 143
  • I'm not sure this will or won't work without a test. My gut instinct is that it won't because i am using a TClientDataSet, which has two "modes" of storing data: actual record state (data as it exists in the DB) and a log state (data changed in clientdataset). These cannot be displayed side by side in a datagrid. But before we shoot it down, lets give it a go. Thank you for your input either way. – Forer Oct 24 '11 at 08:11
  • @ForerMedia, I tried it before I posted the answer, with a TClientDataset, and it worked for me, so let me know. – Marcus Adams Oct 24 '11 at 14:03
0

TClientDataset will handle itself the correct record status. Changes are logged, but unless you ask it explicity to show some other status (see StatusFilter property), it will show the actual state of a record.

It is possible InsertRecord bypasses some notification mechanism, so the field display is not updated. What if you perform simpy an Insert and the set field values?

  • I think the issue is usability related. In one state, you can see the existing data in a record - great. If the user edits or inserts a record, they need visual confirmation of what those edits / insert are before commiting data. Sadly, this cannot be shown alongside other records and just appears as a blank record (though there is data). Thats messed up from a user perspective. A user shouldn't need to commit an insert to be able to see the data they were inserting. – Forer Oct 24 '11 at 08:18
  • The VCL architecture for data display controls requires soem notifications if the data are changed directly on the dataset side. Usually a commit is not needed, did you try to change the insert method and see if it is a notification issue? –  Oct 24 '11 at 08:54
  • Not yet. I will have a look when I get a free moment. This is not a priority right now as the post is a year old. I will take another look, if & when. – Forer Oct 24 '11 at 10:27