12
votes

I have an custom TDatasetProvider that allows to create new fields to whatever data it provides.

So, let's say you got the folowing fields on the original dataset:

  • CustomerId
  • Name
  • Age

And you need to select it on DBGrid using showing an Bitmap. Well, you can since my DSP can add an boolean field called Selected to the dataset data.

The way I do that now:

  1. Create 2 TClientDataset objects (Origin and Target)
  2. In Origin, I load the data got from the parameters of the InternalGetRecords method (I overrode it)
  3. In Target, I create the fielddefs defined from the Origin dataset and add the fielddefs created in design-time by the developer
  4. Execute an CreateDataset on Target
  5. And, row-by-row (and field-by-field), I copy the data from the Origin database to the Target dataset
  6. In the end, return the Data variant as a return value from InternalGetRecords.

I really don't know if there's a more elegant (and faster) way to do that. There's another (faster and/or elegant) way to get that result?

4
can't you simply create internalcalc boolean field right on original dataset without all that mess?vavan
After I made this component, life became easier as I can create data fields that the CDS recognize as data fields..Fabricio Araujo
but you doing lot of unnecessary work. and what's the point of creating those data fields?vavan
They simplify a lot work with customizations of TDbGrid to get the functionality I want. I use it also to mark if the record is imported and order based on the main entity of the result set (which is denormalized)... And the list goes on...Fabricio Araujo
I believe you could achieve the same using internalcalc fields and without copying the data inefficient wayvavan

4 Answers

13
votes

It seems that after loading the data from the source dataset, you can call IDSBase.AddField to add more fields:

uses
  DB, DBCommon, DBClient, DSIntf;

type
  THackClientDataSet = class(TClientDataSet);

procedure EncodeFieldDesc(var FieldDesc: DSFLDDesc;
  const Name: string; DataType: TFieldType; Size, Precision: Integer;
  Calculated: Boolean; Attributes: TFieldAttributes);
begin
  // ... copied from TClientDataSet.EncodeFieldDesc
end;

//...
var
  FldDesc: DSFLDDesc;
begin
  FillChar(FldDesc, SizeOf(FldDesc), 0);
  EncodeFieldDesc(FldDesc, 'SELECTED', ftBoolean, 0, 0, False, []);
  with THackClientDataSet(DataSet) do
    Check(DSBase.AddField(@FldDesc));
  // now you can create a second client dataset and assign it DataSet.Data directly:
  // DataSet2.Data := DataSet.Data;
  // DataSet2 now contains the new field (with empty values in all existing records)
end;

I didn't test it thoroughly but the simple example above worked as expected, I was able to navigate the second client dataset and edit the values of all fields as usual.

1
votes

The fastest way would be to use CloneCursor. Something like this:

  1. Create 2 TClientDataset objects (Origin and Target)
  2. In Origin, load the data got from the parameters of the InternalGetRecords method
  3. In Target, create the fielddefs defined from the Origin dataset and add the fielddefs created in design-time by the developer
  4. Target.CloneCursor(Origin); //there are more params than this, but this is the basic idea
  5. Target will now contain a new view of the same data as Origin, but limited by whatever fields, filters, etc. exist on Target. (If you hadn't defined any fields, it would copy Origin's fields. If you do define fields, then it sticks with what you gave it.)
  6. Copy Data from Target, and that should be exactly what you're looking for.
0
votes

I have a sample that adds fields to a CDS dynamically, using anonymous methods for the calculations of individual fields, to achieve more flexibility. Before opening the CDS, you add the calculated fields, than open it..

Is this is what you are looking for? The question is not very clear...

-1
votes

You can use the Data property of TClientDataset to copy the entire dataset, metadata and data. This is supposed to be the fastest way to copy one TClientDataset to another.

See http://docwiki.embarcadero.com/RADStudio/en/Assigning_Data_Directly