TDataSet OnFilterRecord与OnCalcFields执行顺序及过滤记录可见性相关问题
TDataSet 事件顺序与过滤相关问题解答
1. 事件触发优先级
OnCalcFields 事件的触发顺序早于 OnFilterRecord:
- 数据集打开、记录指针滚动、源字段值发生变更时,会首先触发
OnCalcFields完成所有计算字段的赋值 - 所有字段(含计算字段)值就绪后,才会触发
OnFilterRecord事件,通过Accept参数判断当前记录是否符合过滤规则、是否需要对外展示
2. 被过滤记录的可见性与状态检查
- 后续被设置为
Accept = false的记录在OnCalcFields执行阶段完全可见:OnCalcFields会作用于所有加载到数据集内存中的记录,不受后续过滤逻辑的影响。这也是你开启过滤后求和速度仍然很慢的核心原因:即使最终仅展示少量过滤后记录,3000条全量记录都会触发OnCalcFields中的跨数据集查找逻辑,产生大量冗余计算。 - 记录过滤状态检查方案:
- 通用方案:继承
TFDQuery类暴露其 protected 级别的RecordFiltered属性,该属性可直接返回当前记录是否被过滤排除 - FireDac 专属方案:直接调用
TFDQuery.GetFilterRecordStatus方法获取当前记录的过滤状态
- 通用方案:继承
性能优化建议
针对你当前的性能瓶颈,可以参考以下方案优化:
- 优先在SQL层完成关联查询:将跨数据集查找的逻辑改为SQL语句的JOIN关联,数据库层面的关联查询效率远高于客户端数据集遍历查找
- 缓存计算字段结果:如果必须在客户端实现计算逻辑,仅在关联的源字段值发生变更时更新计算字段值,避免每次
OnCalcFields触发都重复执行查找逻辑 - 求和逻辑避开计算字段:直接统计原始数据字段的和,不要通过遍历数据集触发
OnCalcFields再累加计算字段值
内容的提问来源于stack exchange,提问作者Allan.A
相关产品推荐
相关产品推荐

