I have been investigating what might need to be done to convert my Delphi 10.3.3 app from using TDataSource -> TClientDataSet -> TDataSetProvider -> TIBQuery to using FireDAC.
From all I read it is not a good idea to simply replace TIBQuery with TFDQuery as in TDataSource -> TClientDataSet -> TDataSetProvider -> TFDQuery. This is because TDFQuery is itself is an in-memory dataset and has all the same functionality as the client dataset. Therefore I want to remove the TClientDataSet and the TDataSetProvider components and just have a TDataSource -> TFDQuery components.
That said there is one event of the TDataSetProvider that I have not been able to find a suitable replacement for. That is the OnGetData event. In this event I do additional processing before that data is displayed to the user in the interface.
In the help file for this event it states "Occurs after a provider retrieves data but before it is sent to the client. Write an OnGetData event handler to perform any custom data processing the provider should handle before returning data to a client. The OnGetData event occurs after a provider fetches data from its dataset but before the data is sent on to the client. Using the methods of the DataSet parameter, data can be edited in the OnGetData event handler before sending it to the client dataset."
I use this event extensively in my application.
So does anyone know how I can can do this using just FireDAC FDQuery?
For example I have the following SQL statement in my query
SELECT ACC.ACCT_ID,
ACC.CASE_ID,
ACCG.*,
ATDTM.HAND_FILE_WHEN_FORMAT_IS_EFILE,
ATDTM.ROS_CREATE_DATE,
ATDTM.ROS_CREATE_USER,
ATDTM.ROS_SERV_TYPE_REQ_ID,
ATDTM.ROS_SERV_REQ_WAIT_DAYS,
ATDTM.ROS_MODIFY_DATE,
ATDTM.ROS_MODIFY_USER,
ATDTM.ROS_DATE_OF_SERVICE,
ATDTM.ROS_SERV_TYPE_REC_ID,
ATDTM.ROS_SERVED_TO,
ATDTM.ROS_SERVICE_BY,
CAST(NULL AS VARCHAR(10)) AS ROS_SERVICE_BY_DESC,
ATDTM.ROS_NO_SERV_REASON_ID,
ATDTM.ROS_MEMO,
GS.IMAGE_INDEX AS GARN_STATUS_IMAGE_INDEX,
STR.SERV_TYPE_REQ_CODE AS ROS_SERV_TYPE_REQ_CODE,
STR.DESCRIPTION AS ROS_SERV_TYPE_REQ_DESC,
STR2.SERV_TYPE_REC_CODE AS ROS_SERV_TYPE_REC_CODE,
STR2.DESCRIPTION AS ROS_SERV_TYPE_REC_DESC,
NSTR.DESCRIPTION AS ROS_NO_SERV_REASON_DESC,
CAST(NULL AS VARCHAR(50)) AS DEBTOR_FULL_NAME,
CAST(NULL AS VARCHAR(60)) AS GARNISHEE_NAME,
CAST(NULL AS VARCHAR(20)) AS GARN_TYPE_DESC,
CAST(NULL AS SMALLINT) AS GARN_COMPLETED_IMAGE_INDEX,
CAST(NULL AS INTEGER) AS TRAN_ID,
ATDTM.ROS_COURT_FILE_STAMPED_DATE,
CAST(NULL AS DATE) AS NMA_EMP_TERM_DATE,
ATM.FILING_COUNTY_ID,
C.COUNTY_CODE || C.STATE AS FILING_COUNTY_DESC
FROM ACCT_CASE_COURT_GARNISHMENT ACCG
JOIN ACCT_CASE_COURT ACC ON ACC.ACCT_CASE_COURT_ID = ACCG.ACCT_CASE_COURT_ID
LEFT OUTER JOIN ACCT_TRAN_DETAIL_TASK_MERGE ATDTM ON ATDTM.ACCT_TRAN_ID = ACCG.ACCT_TRAN_ID
AND ATDTM.ACCT_TRAN_DETAIL_ID = ACCG.ACCT_TRAN_DETAIL_ID
AND ATDTM.ACCT_TASK_ID = ACCG.ACCT_TASK_ID
JOIN SERVICE_TYPE_REQ STR ON STR.SERV_TYPE_REQ_ID = ATDTM.ROS_SERV_TYPE_REQ_ID
LEFT OUTER JOIN SERVICE_TYPE_REC STR2 ON STR2.SERV_TYPE_REC_ID = ATDTM.ROS_SERV_TYPE_REC_ID
LEFT OUTER JOIN NO_SERVICE_TYPE_REASON NSTR ON NSTR.REASON_ID = ATDTM.ROS_NO_SERV_REASON_ID
LEFT OUTER JOIN GARN_STATUS GS ON GS.STATUS_CODE = ACCG.GARN_STATUS_CODE
LEFT OUTER JOIN ACCT_TRAN_MASTER ATM ON ATM.ACCT_TRAN_ID = ACCG.ACCT_TRAN_ID
LEFT OUTER JOIN COUNTY C ON C.COUNTY_ID = ATM.FILING_COUNTY_ID
WHERE ACC.ACCT_ID = :ACCT_ID
AND ACC.CASE_ID = :CASE_ID
ORDER BY ACCG.ACCT_TRAN_DETAIL_ID
And then in the TDataSetProvider.OnGetData event I have this
procedure TdtmCaseManagement.prvGarnishmentsGetData(Sender: TObject;
DataSet: TCustomClientDataSet); begin while not DataSet.Eof do begin DataSet.Edit;
if (DataSet.FieldByName('ROS_SERV_TYPE_REC_ID').AsInteger = 1) and
(DataSet.FieldByName('ROS_NO_SERV_REASON_ID').AsInteger = 18) then
DataSet.FieldByName('ROS_SERV_TYPE_REC_DESC').AsString := 'No Return';
with spsGetPersonInfo do
begin
if not Prepared then
begin
Params.Clear;
Prepare;
end;
Params.ParamByName('V_PERSON_ID').AsInteger :=
DataSet.FieldByName('PERSON_ID').AsInteger;
Params.ParamByName('V_LAST_NAME_FIRST').AsInteger := 0;
ExecProc;
DataSet.FieldByName('DEBTOR_FULL_NAME').AsString :=
Params.ParamByName('R_FULL_NAME').AsString;
UnPrepare;
end;
with spsFetchGarnishee do
begin
if not Prepared then
begin
Params.Clear;
Prepare;
end;
Params.ParamByName('V_GARN_TYPE').AsString :=
DataSet.FieldByName('GARN_TYPE').AsString;
Params.ParamByName('V_GARN_ENTITY_ID').AsInteger :=
DataSet.FieldByName('GARN_ENTITY_ID').AsInteger;
ExecProc;
DataSet.FieldByName('GARNISHEE_NAME').AsString :=
Params.ParamByName('R_GARNISHEE_NAME').AsString;
UnPrepare;
end;
DataSet.Post;
DataSet.Next;
end;
end;