【问题标题】:Does TUniQuery (UniDac TUniQuery) Last and First methods jump directly or do a record by record scrollTUniQuery (UniDac TUniQuery) Last 和 First 方法是直接跳转还是逐条记录滚动
【发布时间】:2020-05-26 16:04:05
【问题描述】:

我有一个程序必须在用户转到数据集中的某个记录后设置一个不太复杂的屏幕 (TUniQuery)。用户可以通过多种方式跳转:组合框、搜索框,最后是 DbNavigator。从第一个记录到最后一个记录需要很长时间。在执行程序后,我发现按下 DBNavigator 上的最后一个按钮会导致数据集上的每条记录都被访问,因此,在每条记录上,屏幕都是无用的。从任何记录到第一个或最后一个记录都是一样的。我的理解是,这样的方法(FirstLast)会直接跳转。也许是 Unidac 组件上的一种特殊行为,但我找不到任何参考或属性来修改它。目前,我计划在 BeforeScroll 事件上设置一个标志,但由于 AfterScroll 也发生在每个事件之后,我无法知道数据集何时结束滚动。我在 Delphi 文档中也找不到任何简单说明
调用 Last 以激活数据集中的最后一条记录的参考

【问题讨论】:

  • 它是多用户应用吗?检索太多行(听起来您可能是这样)是对用户不利的事情。
  • 查询和数据库经常决定你是否可以这样跳。尝试使用 TUniTable 或者如果您必须使用 TUniQuery 使查询变得简单并定义关键字段等。
  • 如果查询结果集中的行数多于行缓冲区中的行数,则不能直接跳转。到达缓冲区末尾后,向服务器请求另一组行,然后处理直到到达缓冲区末尾,此时该过程一次又一次地重复,直到到达最后一行。您通常通过使用特定的 SELECT 列列表而不是 SELECT * 来限制要检索的列数并使用 WHERE 限制行数来限制它们来处理此问题。
  • 您可以通过在调用FirstLast 之前禁用前后滚动事件来解决此问题,然后在之后恢复它们(在finally 块中)。跨度>
  • 不可能,肯。 First 和 Last 由 TDBNavigator 调用。在这种情况下,行数很少,并且可以直接跳转,因为已获取所有记录(特别是四个)

标签: delphi unidac


【解决方案1】:

按照源代码,我发现了这一点:
简答:是的,TDataset 会尽可能直接跳转到第一条和最后一条记录,但是......

长答案:Delphi 具有广播的内部数据事件(DB 单元,TDataEvent),因此数据感知控件可以正确更新。 NextPrior 和许多其他方法使用函数 MoveBy,它生成 Before/AfterScroll 事件以及内部事件。如果需要,MoveBy 可能会获取一些额外的行。假设您从 30 行数据集中提取了 20 行。你目前的记录是十五。您调用 MoveBy(2)。不出所料,你的新纪录是十七岁。在这种情况下会发生以下情况:

  1. 滚动前
  2. ActiveRecord 递增两次(在循环中),但未提取任何行
  3. 内部数据事件:deDataSetScroll
  4. 后滚动

请注意,滚动时不会发生任何程序事件。 BeforeScroll 出现在记录十五,AfterScroll 出现在记录十七。

现在,同样的场景,但这次调用 MoveBy(10)。已经提取了五行(20 - 15),还需要检索五行。在这种情况下,顺序是:

  1. 滚动前
  2. ActiveRecord 递增 5(在循环中),但未获取任何行
  3. 活动记录在同一循环中增加 5。在每个循环中,都会获取一条记录(不发生程序事件)
  4. 内部数据事件:deDataSetChange
  5. 后滚动

一切运行良好。 Last 方法引发了问题,该方法不使用 MoveBy 并假设记录是总是 获取的:

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 应该检查是否确实检索到了记录。

有些人会说我自己很容易实现,当你的代码滚动数据集时确实如此。但在 TDBNavigatorTJvDBSearchComboBox 的情况下,我无法控制它们。其他人会说不要使用 JVCL,这里没有简单的答案。此外,仅供参考,First 方法表现出相同的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-26
    • 2023-03-13
    • 2016-07-10
    • 2023-03-17
    • 1970-01-01
    • 2022-01-23
    • 2011-01-19
    • 1970-01-01
    相关资源
    最近更新 更多