1
votes

On the TDatasetProvider.OnBeforeUpdateRecord, how do I access the source or originating clientdataset of the sent DeltaDS parameter?

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
    SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
    var Applied: Boolean);
var
  sourceCDS: TClientDataset;
begin
  sourceCDS := DeltaDS.???;
  ...
end;

I need to access some properties from the corresponding clientdataset. Setup is TSQLDataset/TDatasetProvider/TClientDataset.

Edit: The cause of all this hassle is, I wanted to derive a component from TDatasetProvider and assign a default OnBeforeUpdateRecord.

2
You seem to be somewhat confused. SourceDS is the source (originating) dataset, and DeltaDS contains the changes that have occurred in SourceDS. - Ken White
Thanks Ken, but I'm not confused. I know what SourceDS is. What I want to know is which Clientdataset generated the DeltaDS in question. - JeffP
Of course, while designing, this is not really a problem because I can tell which CDS is connected. But I am trying to abstract this process. - JeffP
What is mean "default OnBeforeUpdateRecord"? Is not OnBeforeUpdateRecord event of the provider? - Val Marinov
@ValMarinov, I wanted to derive/descend a component from TDatasetProvider. On this descendant component I will assign an OnBeforeUpdateRecord that will always be evaluated. Inside this OnBeforeUpdateRecord I wanted to know the Clientdataset that generated/parented the delta that was passed to this event. - JeffP

2 Answers

0
votes

I think SourceDS is what are looking for.

The Sender parameter identifies the provider that is applying updates.

The SourceDS parameter is the dataset from which the data originated. If there is no source dataset, this value is nil (Delphi) or NULL (C++). The source dataset may not be active when the event occurs, so set its Active property to true before trying to access its data.

The DeltaDS parameter is a client dataset containing all the updates that are being applied. The current record represents the update that is about to be applied.

The UpdateKind parameter indicates whether this update is the modification of an existing record (ukModify), a new record to insert (ukInsert), or an existing record to delete (ukDelete).

The Applied parameter controls what happens after exiting the event handler. If the event handler sets Applied to true, the provider ignores the update: it neither tries to apply it, nor does it log an error indicating that the update was not applied. If the event handler leaves Applied as false, the provider tries to apply the update after the event handler exits.

for example:

procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  ShowMessage(TClientDataSet(SourceDS).Name); // get source name
  ...
end;

Edit

or

  procedure TdmLoanPayment.dpLoanPaymentBeforeUpdateRecord(Sender: TObject;
SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind:  TUpdateKind;
var Applied: Boolean);
begin
  if SourceDS.Name = 'Name1'then
    ...do something ...
  if SourceDS.Name = 'Name2'then
    ...do something ... 
end;
0
votes

If you trace out of the call to your DataSetProvider1BeforeUpdateRecord, you'll see that the dataset passed as the SourceDS parameter is the Source dataset of the UpdateTree, and that is, AFAICS, the dataset that the DataSet property of the Provider is set to. Of course, this is not the CDS from which the Delta has been derived (in my test case it's actually a TAdoQuery).

Looking at the source code in Provider.Pas, I can't immediately see a way to find the identity of the Delta's source CDS. I don't think that is particularly surprising because the Provider's operation is invoked by a CDS and not vice versa, and all the data the Provider needs from the CDS is its Delta.

On the other hand, it's a pretty fair bet that the BeforeUpdateRecord event has been triggered by the most recent, still-pending, call to ApplyUpdates on one of your CDSs, so if you make a note of that in their BeforeApplyUpdates event(s), that will probably tell you what you want to know. I'd expect that to work for a single-level update, but it might be more tricky if the UpdateTree is operating on nested CDSs.

If your CDSs all have individual Providers, but the providers share a BeforeUpdateRecord event, you could identify the CDS for a given provider using code like this:

function TCDSForm.FindCDSForProvider(DataSetProvider: TDataSetProvider):
    TClientDataSet;
var
  i : Integer;
begin
  Result := Nil;
  for i := 0 to ComponentCount - 1 do begin
    if Components[i] is TClientDataSet then
      if TClientDataSet(Components[i]).ProviderName = DataSetProvider.Name then begin
        Result := TClientDataSet(Components[i]);
        Exit;
      end;
  end;
end;