In the AfterPost event handler for a ClientDataSet, I need the information if the ApplyUpdates function for the current record will do an update or an insert.

The AfterPost event will be executed for new and updated records, and I do not want to declare a new Flag variable to indicate if a 'update' or ' insert' operation is in progress.

Example code:

procedure TdmMain.QryTestAfterPost(DataSet: TDataSet);begin  if IsInserting(QryTest) then     // ShowMessage('Inserting')...  else     // ShowMessage('Updating');  QryTest.ApplyUpdates(-1); end;

The application will write a log in the AfterPost method, after ApplyUpdate has completed. So this method is the place which is closest to the action, I would prefer a solution which completely can be inserted in this event handler.

How could I implement the IsInserting function, using information in the ClientDataSet instance QryTest?

Edit: I will try ClientDataSet.UpdateStatus which is explained here.

asked Jul 8 '09 at 7:51
mjn
24.3k19129286
    
What do you plan to do? Do validations, update user interface or some data manipulation? – zendar Jul 8 '09 at 12:35
    
The application will write a log in the AfterPost method, after ApplyUpdate has completed. So this method is the place which is closest to the action, I would prefer a solution which completely can be inserted in this event handler. Checking the Delta array here seems to be the easiest way. – mjn Jul 8 '09 at 13:47
    
This is best place if you log per user, on client side. If you want to central log for all users, better place would be on server side in AfterApplyUpdates event on TDataSetProvider. – zendar Jul 9 '09 at 14:45
up vote 4 down vote accepted

ApplyUpdates doesn't give you that information - since it can be Inserting, updating and deleting.

ApplyUpdates apply the change information stored on Delta array. That change information can, for example, contain any number of changes of different types (insertions, deletions and updatings) and all these will be applied on the same call.

On TDatasetProvider you have the BeforeUpdateRecord event (or something like that, sleep does funny things on memory :-) ). That event is called before each record of Delta is applied to the underlying database/dataset and therefore the place to get such information... But Showmessage will stop the apply process.

EDIT: Now I remembered there's another option: you can assign Delta to another clientdataset Data property and read the dataset UpdateStatus for that record. Of course, you need to do this before doing applyupdates...

var  cdsAux: TClientDataset;begin  .  .   <creation of cdsAux>  cdsAUx.Data := cdsUpdated.Delta;  cdsAux.First;  case cdsAux.UpdateStatus of    usModified:      ShowMessage('Modified');    usInserted:      ShowMessage('Inserted');    usDeleted:      ShowMessage('Deleted'); // For this to work you have to modify                                // TClientDataset.StatusFilter    end;  <cleanup code>end;
answered Jul 8 '09 at 8:21
Fabricio Araujo
3,0761941
    
This sounds very good. If the ApplyUpdate is only related to one record, the Delta arry will only contain one entry which knows if it is an update or insert? So I need only a way to access this information in the Delta. – mjn Jul 8 '09 at 8:39
    
Why does it use a second CDS? I would expect that the UpdateStatus is already available in the first CDS, so I could just read it directly. Or is StatusFilter the answer why a second one is needed? – mjn Jul 9 '09 at 8:15
    
Because with the 2nd cds you'll have just content of the Delta, and nothing more. But it's just an alternative way to do the thing, without going through the dataset provider. – Fabricio Araujo Jul 9 '09 at 13:59
    
This is the solution I was dreaming of - with the only addition that the dataset needs to be filtered as explained in Cary Jensens answer, to avoid the unmodified delta records. I am using this now in a demo for database change notifications over a message broker (Apache ActiveMQ or OpenMQ). – mjn Aug 19 '09 at 12:29

Did you find this question interesting? Try our newsletter

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

BeforeUpdateRecord event on TDataSetProvider is defined as:

procedure BeforeUpdateRecord(Sender: TObject;  SourceDS: TDataSet; DeltaDS:                             TCustomClientDataSet; UpdateKind: TUpdateKind;                             var Applied: Boolean);

Parameter UpdateKind says what will be done with record: ukModify, ukInsert or ukDelete. You can test it like this:

procedure TSomeRDM.SomeProviderBeforeUpdateRecord(Sender: TObject;      SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind;      var Applied: Boolean);begin  case UpdateKind of    ukInsert :         // Process Insert;    ukModify :         // Process update    ukDelete :         // Process Delete  end;end;

Note: this event signature is from Delphi 7. I don't know if it changed in later versions of Delphi.

answered Jul 8 '09 at 8:55
zendar
8,650114669

Set the ClientDataSet.StatusFilter to an TUpdateStatus value, and then read ClientDataSet.RecordCount

for example,

 ClientDataSet1.StatusFilter := [usDeleted]; ShowMessage(IntToStr(ClientDataSet1.RecordCount));

will return the number of Delete queries that will be executed.

Note two things, however. Setting StatusFilter to usModified always includes both the modified and unmodified records, so you take half of that value (a value of 4 means 2 Update queries will be executed). Also, setting StatusFilter to [] (an empty set) is how you restore to default view (Modified, Unmodified, and Inserted)

Make sure that any unposted changes have been posted before doing this, otherwise unposted changes may not be considered.

answered Jul 10 '09 at 20:45
Cary Jensen
1,9942040
    
Many thanks, this was the missing piece of the easiest solution! See my comment in the answer from Fabricio Araujo. – mjn Aug 19 '09 at 12:30