Delphi中设置Firedac DateTime格式兼容BDE应用的方案问询
Firedac适配BDE DateTime精度配置方案
你遇到的问题本质是Firedac默认存储的DateTime精度高于BDE的TDateTime支持的精度。BDE的TQuery默认将数据库DateTime字段映射为TDateTime(Double类型,实际在BDE的SQL参数处理时会自动截断毫秒部分,仅保留到秒级精度),而Firedac默认会保留完整的毫秒甚至更高精度写入数据库,导致BDE端执行更新时,用自己读出的低精度DateTime值作为WhereAll的匹配条件,和数据库里存储的高精度值匹配不上,最终返回更新行数为0抛出错误。
以下方案均仅修改Firedac配置,无需改动旧BDE应用代码:
方案1:全局配置Firedac自动截断DateTime到秒级(最省事)
直接修改Firedac连接配置即可全局生效,无需修改业务代码:
- 找到你的Firedac连接组件,打开
Params属性,添加如下两行参数:DateTimeFormat = dtfDateTime DateTimePrecision = 0 - 也可以在代码初始化连接时动态赋值:
FDConnection1.Params.Add('DateTimePrecision=0'); FDConnection1.Options.FormatOptions.DateTimePrecision := 0;
参数DateTimePrecision设为0的含义是:所有DateTime类型的值写入数据库时,自动截断到秒,完全对齐BDE的存储精度,旧BDE端的WhereAll匹配逻辑即可正常生效。
方案2:调整映射规则(适配你之前尝试的配置逻辑)
你之前配置的映射规则未生效,是因为没有开启精度应用开关,正确配置如下:
- 打开Firedac连接的
MappingRules集合 - 新增第一条映射规则:
- 源类型:
DateTimeStamp - 目标类型:
DateTime - PrecMax:
0 ApplyPrecision属性设为True
- 源类型:
- 新增第二条映射规则:
- 源类型:
DateTime - 目标类型:
DateTime - PrecMax:
0 ApplyPrecision属性设为True
配置完成后,Firedac会自动将所有DateTime类型的值做精度截断后再写入数据库。
- 源类型:
方案3:全局事件拦截处理(适合需要自定义精度的场景)
如果业务需要保留部分时间精度,也可以通过Firedac全局事件统一处理:
- 实现一个通用的DateTime精度截断函数,对齐BDE的存储精度:
function TruncDateTimeToBDE(const AValue: TDateTime): TDateTime; begin // 截断到秒级,和BDE处理逻辑完全对齐 Result := Trunc(AValue) + Trunc(Frac(AValue) * 86400) / 86400; end; - 给Firedac连接绑定
BeforePost全局事件,在数据写入前自动处理所有DateTime字段:procedure TMainForm.FDConnection1BeforePost(ASender: TDataSet; AAction: TFDEventAction; var ADefault: Boolean); var I: Integer; begin for I := 0 to ASender.FieldCount - 1 do begin if ASender.Fields[I].DataType = ftDateTime then ASender.Fields[I].AsDateTime := TruncDateTimeToBDE(ASender.Fields[I].AsDateTime); end; end;
验证方法
配置完成后,用Firedac写入一条带DateTime字段的测试记录,直接在数据库执行SQL查询该字段的毫秒部分,如果毫秒为0则说明配置生效,此时再用旧BDE应用修改该条记录即可正常更新。
内容的提问来源于stack exchange,提问作者Dirk Janssens
相关产品推荐
相关产品推荐

