delphidelphi-xe2tclientdataset

How to force a Client DataSet to recalculate calculated and internal calculated fields?


I have a ClientDatSet with a few fkInternalCalc fields. The CDS is not linked to any provider; instead it's filled on the fly. How can I force CDS to recalculate all the "calculable" fields? I can not call Refresh() because there is no provider to refresh data from. The only way I have come with so far has been to navigate through all records, which is not the best way.

PS: I have read this question and this post, but I'm hoping for a more elegant way.


Solution

  • I achieve that with a helper (stripped here to the necessary), which allows to call the protected methods without any hack. Make sure to check for DataSet.State = dsInternalCalc inside OnCalcFields for fkInternalCalc fields.

    type
      TClientDataSetHelper = class helper for TClientDataSet
      public
        function AssureEditing: Boolean;
        procedure InternalCalc;
      end;
    
    function TClientDataSetHelper.AssureEditing: Boolean;
    begin
      result := not (State in [dsEdit, dsInsert]);
      if result then
        Edit;
    end;
    
    procedure TClientDataSetHelper.InternalCalc;
    var
      needsPost: Boolean;
      saveState: TDataSetState;
    begin
      needsPost := AssureEditing;
      saveState := setTempState(dsInternalCalc);
      try
        RefreshInternalCalcFields(ActiveBuffer);
      finally
        RestoreState(saveState);
      end;
      if needsPost then
        Post;
    end;
    

    This can easily be expanded for normal calculated fields using CalculateFields. Although this shouldn't be necessary as calculated fields are recalculated whenever any other data field changes.