我一直在研究将我的 Delphi 10.3.3 应用程序从使用 TDataSource -> TClientDataSet -> TDataSetProvider -> TIBQuery 转换为使用 FireDAC 可能需要做的事情。
从我读到的所有内容来看,在 TDataSource -> TClientDataSet -> TDataSetProvider -> TFDQuery 中简单地将 TIBQuery 替换为 TFDQuery 并不是一个好主意。这是因为 TDFQuery 本身就是一个内存数据集,并且具有与客户端数据集相同的功能。因此,我想删除 TClientDataSet 和 TDataSetProvider 组件,只拥有一个 TDataSource -> TFDQuery 组件。
也就是说,有一个 TDataSetProvider 事件我无法找到合适的替代品。那就是 OnGetData 事件。在这种情况下,我会在数据在界面中显示给用户之前进行额外的处理。
在此事件的帮助文件中,它声明“在提供程序检索数据之后但在将数据发送到客户端之前发生。编写 OnGetData 事件处理程序以执行提供程序在将数据返回到客户端之前应处理的任何自定义数据处理。OnGetData 事件在提供程序从其数据集中获取数据之后但在将数据发送到客户端之前发生。使用 DataSet 参数的方法,可以在将数据发送到客户端数据集之前在 OnGetData 事件处理程序中编辑数据。
我在我的应用程序中广泛使用此事件。
那么有谁知道我怎么能只使用 FireDAC FDQuery 来做到这一点?
例如,我的查询中有以下 SQL 语句
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
然后在 TDataSetProvider.OnGetData 事件中我有这个
procedure TdtmCaseManagement.prvGarnishmentsGetData(Sender: TObject;
数据集:TCustomClientDataSet); 开始而不是 DataSet.Eof 开始 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;
结尾;