[英]Does TUniQuery (UniDac TUniQuery) Last and First methods jump directly or do a record by record scroll
我有一个程序必须在用户转到数据集中的某个记录(TUniQuery)后设置一个更简单的屏幕。 用户可以通过多种方式跳转:combobox、搜索框,最后是 DbNavigator。 从第一个记录到最后一个记录需要很长时间。 在执行程序之后,我发现按下 DBNavigator 上的最后一个按钮会导致数据集上的每条记录都被访问,因此,在每条记录上,屏幕都是无用的。 从任何记录到第一个或最后一个记录都是一样的。 我的理解是,这样的方法( First和Last )会直接跳转。 也许是 Unidac 组件上的一种特殊行为,但我找不到任何参考或属性来修改它。 目前,我计划在BeforeScroll事件上设置一个标志,但由于AfterScroll也发生在每个事件之后,我无法知道数据集何时结束滚动。 我在 Delphi 文档中也找不到任何简单说明的参考
调用 Last 以激活数据集中的最后一条记录
按照源代码,我发现了这个:
简短回答:是的,TDataset 尽可能直接跳转到第一条和最后一条记录,但是......
长答案:Delphi 具有广播的内部数据事件( DB单元, TDataEvent ),因此数据感知控件可以正确更新。 Next , Prior和许多其他方法使用 function MoveBy ,它生成一个Before/AfterScroll事件和内部事件。 如果需要, MoveBy可能会获取一些额外的行。 假设您从 30 行数据集中提取了 20 行。 你目前的记录是十五。 你打电话给MoveBy(2) 。 不出所料,你的新纪录是十七岁。 在这种情况下,会发生以下情况:
请注意,滚动时不会发生任何程序事件。 BeforeScroll出现在记录十五和AfterScroll在十七。
现在,同样的场景,但这次调用了MoveBy(10) 。 已经提取了五行(20 - 15),还需要检索另外五行。 在这种情况下,顺序是:
每件事都运行良好。 不使用MoveBy并假定始终获取记录的Last方法会出现问题:
procedure TDataSet.Last;
begin
CheckBiDirectional;
CheckBrowseMode;
DoBeforeScroll;
ClearBuffers;
try
InternalLast;
GetPriorRecord;
GetPriorRecords;
finally
FEOF := True;
DataEvent(deDataSetChange, 0); // Problem! Causes TJvDBSearchComboBox to retrieve all records (again)
DoAfterScroll;
end;
end;
如您所见,即使所有记录都已获取, Last方法也始终广播deDataSetChange事件。 在我的四个记录的特殊情况下,用户按下TDBNavigator的最后一个按钮,该按钮又调用Last方法。 广播deDataSetChange事件,然后TJvDBSearchComboBox (来自 JVCL 库)通过使用“while not eof...next”循环访问每一行来更新其内容并生成Before/AfterScroll事件来对此事件做出反应。
我喜欢 Delphi,但这是我不喜欢数据集的原因之一。 程序无法了解是否由于用户操作或程序本身触发了某些数据事件。 我在 Delphi 演示文稿中提出了一种在不触发事件的情况下遍历数据集的方法(如MoveBy所做的那样),然后,像TJvDBSearchComboBox这样的组件可以使用它,或者至少可以打开数据集中的标志等在开始访问每条记录之前。 此外, Last应该检查是否确实检索到了记录。
有些人会说这很容易由我自己实现,而且确实是当您的代码滚动浏览数据集时。 但在TDBNavigator和TJvDBSearchComboBox的情况下,我无法控制它们。 其他人会说不要使用 JVCL,这里没有简单的答案。 此外,仅供参考,第一种方法表现出相同的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.