使用FDQuery.RecordCount来判断查询是否为空可能会在Delphi中返回负值

时间:2017-10-11 11:11:30

标签: database delphi firedac

我在表单上有一个FDQuery,以及根据其recordCount启用和禁用组件的操作(在> 0时启用)。

大多数时候,recordCount属性返回查询中的实际记录数。有时,recordcount返回负值,但我可以看到与查询关联的网格上的记录。
RecordCount返回的值介于-5和-1之间,直到现在。

我该如何解决这个问题?为什么它会返回负值?

1 个答案:

答案 0 :(得分:1)

  

为什么会返回负值?

这不是特定于FireDAC的,这是提供TDataSet接口的所有Delphi库的正常行为。

TDataSet.RecordCount从未得到过保证。它甚至在文档中说。这是一个额外的功能。有时它可能会起作用,有时则不起作用。它只能对CSV,DBF,Paradox表和其他类似ISAM引擎等非SQL表数据可靠地工作。

  

我该如何解决这个问题?

在现代世界中依靠这一功能始终是一项冒险的尝试。 因此,您可以更好地设计程序,以便永远不会使用此功能,或仅在极少数特定情况下使用。 相反,你应该明白你的程序真正要求图书馆提出什么问题,然后找到一个"语言"通过调用其他功能来提出这个问题,更适合您的情况。

现在告诉我,当你在谷歌搜索时,你经常阅读第10页,最多第100页?几乎没有,对吗?您的程序用户也几乎永远不会向下滚动数据网格。记住这一点。 您始终需要向用户显示第一个数据并快速执行。但很少有最后的数据。

现在,有三个例子。

1)您从某些远程服务器读取数据,网络速度较慢。您每秒只能读取100行。你的网格有空间显示20个第一行。其余用户必须滚动。总的来说,查询可以为您过滤10 000行。

如果您只是向用户显示这20行 - 那么它几乎可以立即工作,从您开始读取数据到填充网格并将其呈现给用户只需0.2秒。只有当用户通过滚动请求时才会获取其余数据(为了清楚起见,我在这里稍微简化一下,我知道预缓存TDataset.Buffers)。

因此,如果您调用RecordCount函数,您的程序会执行什么操作?它会将所有记录下载到您计算的本地内存中。如此速度需要10 000/100 = 100秒,超过一分半钟 只需调用您调用RecordCount过程的FetchAll函数,就可以在0.2秒内但在1分40秒内对用户做出程序响应。
用户会非常紧张,等待完成。

2)想象一下,您正在从某些存储过程中获取数据。或者从表中,另一个应用程序插入行。换句话说,这不是一些静态只读数据,即在下载时生成的实时数据 那么,有多少行呢?例如,这一刻是1000行,在一秒钟内它将是1010行,在两秒钟内它可能是1050行,依此类推。
当这个值不时被改变时,One True Value是什么?

Oookey,你调用了RecordCount函数,你SetLength - 将你的数组编辑为1000,现在你从查询中读取了所有数据。但是下载数据需要一些时间。它通常很快,但它永远不会瞬间完成。因此,例如,您花了一秒钟将数据库查询数据的1000行下载到您的数组(或网格)中。但是当你这样做时,会生成/插入10行,而你的查询不是.EOF,并且你继续获取行#1001,#1002,...#1010 - 然后你把它们放在数组中/ gris行只是不存在!

会不会好?

或者当你走出数组/网格边界时,你会取消查询吗? 这样你就不会有访问冲突 但相反,你会忽略并错过那些最近的10行。

这样好吗?

3)您的查询在调试时返回10 000行。您可以通过调用RecordCount函数将它们全部下载到程序的本地内存中,它就像魅力一样,然后部署它。

您的客户端使用您的程序,数据会增长,有一天您的查询返回的不是10 000行,而是10 000 000。 您的程序调用{​​{1}}函数来下载所有这些行,它下载例如9 000 000百万...
....然后它因RecordCount错误而崩溃。

  

根据其recordCount>启用和禁用组件0

这是获取您不需要的数据(确切数量的行)的错误方法,然后丢弃它。上面的例子向您展示了如何使您的程序变得脆弱和缓慢。

你真正想知道的是,是否有任何行或根本没有。 您无需计算广告了解其金额的所有行,您只想知道查询是否为空。

这正是您应该通过调用Out Of Memory函数而不是TDataSet.IsEmpty来提出的问题。