One would hope sth. like this would work (at least when there are no calculated fields);
uses
dsintf;
[..]
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.First;
while not ClientDataSet1.Eof do begin
PRecInfo(ClientDataSet1.ActiveBuffer +
ClientDataSet1.RecordSize).Attribute := dsRecNew;
ClientDataSet1.Next;
end;
end;
Well, it works, but as long as no data is re-retrieved. That is, TCustomClientDataSet.GetRecord
re-sets the record attributes. This renders the hacky approach pretty useless I guess.
Maybe one could try binding a data-aware control and see if setting the BufferCount of the DataLink of the DataSource would help. Or, try overriding GetRecord in a descendant ClientDataSet. But I doubt it is worth the effort.
[EDIT]
The record attribute can be hacked in an "AfterScroll" event. This would help, for instance, code testing the UpdateStatus to return "usInserted".
procedure TForm1.ClientDataSet1AfterScroll(DataSet: TDataSet);
begin
PRecInfo(DataSet.ActiveBuffer + DataSet.RecordSize).Attribute := dsRecNew;
end;
Test if all the records are inserted
procedure TForm1.Button1Click(Sender: TObject);
begin
ClientDataSet1.First;
while not ClientDataSet1.Eof do begin
if not (ClientDataSet1.UpdateStatus = usInserted) then
raise Exception.Create('The record is not inserted');
ClientDataSet1.Next;
end;
end;
A new TClientDataSet can be derived to retrieve always "inserted" records.
(The type declaration goes before the form/datamoule containing the ClientDataSet)
type
TClientDataset = class(dbclient.TClientDataSet)
function GetRecord(Buffer: PChar; GetMode: TGetMode; DoCheck: Boolean):
TGetResult; override;
end;
[..]
implementation
function TClientDataset.GetRecord(Buffer: PChar; GetMode: TGetMode;
DoCheck: Boolean): TGetResult;
begin
Result := inherited GetRecord(Buffer, GetMode, DoCheck);
if Result = grOk then
PRecInfo(Buffer + RecordSize).Attribute := dsRecNew;
end;
Now for all records, UpdateStatus will return "usInserted".
EDIT
I finally understood that the aim is to generate insert SQLs for all records. We won't achieve this by modifying records' attributes of the DataSet, ApplyUpdates takes only the "Delta" into consideration and we possibly have no Delta. There might be different ways to achieve this, the below example assumes the DataSet has a Provider and we are able to put an event handler on it.
type
TForm1 = class(TForm)
[..]
private
procedure DeltaAfterScroll(DataSet: TDataSet);
[..]
implementation
procedure TForm1.DeltaAfterScroll(DataSet: TDataSet);
begin
// The UpdateTree of the Resolver of the Provider will visit each
// record to get the UpdateStatus
PRecInfo(DataSet.ActiveBuffer + DataSet.RecordSize).Attribute := dsRecNew;
end;
type
TAccessCCDS = class(TCustomClientDataSet);
procedure TForm1.Button1Click(Sender: TObject);
var
Count: Integer;
begin
ClientDataSet1.MergeChangeLog;
// Since there's no "Delta", ApplyUpdates will return immediately.
// Hence, we'll force an update by calling DoApplyUpdates, bypassing the
// ChangeCount test, and update with the "Data".
// Reconcilation is left out for simplicity.
TAccessCCDS(ClientDataSet1).DoApplyUpdates(ClientDataSet1.Data, 0, Count);
end;
procedure TForm1.DataSetProvider1UpdateData(Sender: TObject;
DataSet: TCustomClientDataSet);
begin
// Will be called once when ApplyUpdates is called.
TAccessCCDS(DataSet).AfterScroll := DeltaAfterScroll;
end;