views:

238

answers:

2

hi, Is there any way to manually track the changes done to a clientdataset's delta and update the changes manually on to then db. i have dynamically created a clientdataset and with out a provider i am able to load it with a tquery, now user will do some insert update and delete operations on the data available in the cds, and at final stage these data(modified) should be post in to database by using a tquery(not apply updates)..

+1  A: 

After populating your data set from the TQuery call MergeChangeLog so that the records do not stand out as newly inserted, and be sure that LogChanges is set.

Then when at the final stage, before updating the query with the dataset, set StatusFilter so that only the records that you want to take action on should be showing. For instance;

ClientDataSet1.StatusFilter := [usDeleted];

You can also use UpdateStatus on a record to see if it has been modified etc..

But be careful that, is seems that there will be multiple versions of a record, and it is a bit difficult to understand how the "change log" keeps track. And there also can be multiple actions on a record, like modifying it a few times and then deleting it.

Sertac Akyuz
In which event can i use this UpdateStatus?
Vijay Bobba
It is a method of the TClientDataSet which retrieves a value depending on the status of the current record; `if ClientDataSet1.UpdateStatus = usInserted then`.. In your scenario you can use it while you are done with the dataset and it is time to update the query with the records in it, while looping a set of records for instance. See this page in the documentation: http://docwiki.embarcadero.com/RADStudio/en/Indicating_What_Records_Are_Modified and of course the pages about StatusFilter and UpdateStatus of TCustomClientDataSet.
Sertac Akyuz
@Sertac, the problem is when we are done with the dataset and when its time to update the changes the UpdateStatus is the status of the last modified record. At this last moment i wank to trace through all the records(modified-update/insert/delete) of the delta and manually update the modifications with a TQuery.
Vijay Bobba
@Sertac, also the code mentioned in the specified URL indicates about the OnCalcFields event to find the modified records at that instance of time. Now, this event fires only when we have a calculated field defined in the CDS, my doubt is 'is there only this way for my problem' or we have any other without calculated field...?...
Vijay Bobba
clearly my problem is, "say suppose a saleman goes to different shops and collect data in a disconnected architecture(nothing but using CDS), so he enters all the sales data(disconnected - into CDS)into the system and once he comes back to the work location with the modified cds data(delta) and connects to the network the information has to be updated on the database, here at this point i must have a method which takes a delta as a perameter and uses TQuery to apply the changes(with out using the applychanges method).
Vijay Bobba
@Vijay - UpdateStatus is the status of the "current" record, you can loop through a dataset visiting each record, and take action depending on the update status. For instance I'd hope sth. like this to work; set StatusFilter of the dataset to `[usModified, usInserted, usDeleted]`, then `dataset.First` then `while not dataset.eof do begin`, test the record's UpdateStatus, take action, then `dataset.next;`. However, in my tests the above StatusFilter includes the 'deleted' records alright, but their status turns up to be "usModified", but a StatusFilter of [usDeleted] also works... continue...
Sertac Akyuz
..continued.., so it seems that the behavior with `UpdateStatus` and `StatusFilter` is either buggy or it's not easily clear that how they work. Taking into consideration that a ClientDataSet is able to `ApplyUpdates`, I'd think the second option to be correct but I'm not sure. You have to fiddle around a bit to work out this I guess. Or, Pham's solution also looks interesting; what do you get with his solution if you again call `MergeChangeLog` before the user starts to work with the dataset?
Sertac Akyuz
@Vijay - you don't need calculated fields, the example provides a means to present visual information about the UpdateStatus of the records. For instance attach a dbgrid to your dataset and add a calculated field and proceed as in the example, and you'll see the status of the records as you modify/insert/delete records... You can loop through the dataset any time you want, like in an OnClick of a button, and get the UpdateStatus of the records.
Sertac Akyuz
@Sertac, MergeChangeLog clears the delta, i.e., merges the changes to the delta with the data in the cds and delta is cleared
Vijay Bobba
@Sertac - there is lot of difference in the code behaviour when i introduced the StatusFilter (which i have'nt used with the pham's code) let me check and update u...
Vijay Bobba
..continued.., when a record is modified in the dbgrid, the UpdateStatus is UsInserted for all records in the grid + the modified record at the end(with UsInserted), humm problem in identifying the modified records...:-P
Vijay Bobba
@Vijay - read the first sentence of the answer again; call 'MergeChangeLog' after you populate the dataset from the query - but before user starts to work. Then you'll have 'usUnmodified' records in the session start.
Sertac Akyuz
@Sertac, you are wonderful... it works! sorry i hav'nt followed your first step soon after populating the dataset from TQuery.. Thanks a lot.
Vijay Bobba
@Vijay - you're welcome! I had deleted my last comment to have it modified, I'll put it again for if anybody might decide to go through the same route. Since you've resolved your issue just ignore it. Thanks!
Sertac Akyuz
In the final stage: loop through the dataset; when you encounter a 'usModified' record read `OldValue`s for key fields, find the record in the Query and modify it with current values. If you encounter a "usInserted" record, insert it to the Query. At last step set 'StatusFilter' to 'usDeleted' and delete all corresponding records from the Query for records with status 'usDeleted'. When status is 'usModified' read 'OldValue's for key fields, locate the record in the Query and delete. When status is 'usInserted', ignore these records, they've been added and deleted during the session.
Sertac Akyuz
A: 
Change:= TPacketDataSet.create;

Change.Data:= YourClientDataSet.Delta;
while not Change.Eof do
begin
 Change.InitAltRecBuffers(False);
 if Change.UpdateStatus = usUnmodified then
   Change.InitAltRecBuffers(True);

 case Change.UpdateStatus of
  usModified:  ;//your logic read codes in Provider.pas for further hint
  usInserted:  ;//your logic read codes in Provider.pas for further hint
  usDeleted: ;//your logic read codes in Provider.pas for further hint
 end;

 Change.Next;
end;

Above should work regardless of number of modified Cheers Pham

Pham
Be careful with that approach, if a record is multiple times modified, or modified and then deleted, you might not find which record is modified/deleted. You've to go through the change log (I think...).. What is IntAltRecBuffers?, I can't find such thing in D2007... You can use the "Code Sample" button above the edit area when answering a question to have code appear properly formatted.
Sertac Akyuz
@Pham, this code is not going to work because at the final stage say suppose in a 'saveRecords' button click, the Change.UpdateStatus is always usInserted
Vijay Bobba