`First` 是否应该总是在查询的 `Open` 之后被调用 / `TDataset`?

Should `First` always be called after `Open` of a query / `TDataset`?

我习惯于在遍历查询结果时总是调用 First()

Qry.Open;
Qry.First;
while not Qry.Eof do
begin
    //do something
    Qry.Next;
end;

Open() 之后没有自动调用 First() 是有原因的吗?

或以另一种方式询问:我们使用某种数据库访问抽象类。将对 First() 的调用包含到我们的 Open() 例程中是个好主意吗?

我认为 'First' 不需要在数据集的 'Open' 之后调用。 它需要在迭代之前调用,以确保它将访问数据集上的所有记录。

您展示了为什么绝对需要 First 的完美示例:由于您没有在迭代后关闭数据集,因此对该代码序列的新调用不会真正打开数据集。它仍然是打开的,对 Open 的调用静静地什么也不做。因此需要 First 来使迭代工作。

严格来说,归结为希拉里奥所说的:迭代前需要First

在遥远的过去(BDE 时代),我记得读过或听说过打开查询的规范并不坚持将查询放在数据集的开头。但是,我检查的所有查询组件确实在代码中的某处包含 first() 。

我曾经对查询组件进行子类化以包含 first(),但现在不用了,因为我认为没有必要。我使用的所有查询都在第一条记录处打开。

追踪 ADO 查询 open() 的代码发现这段代码似乎在打开后将数据集留在第一个位置。

procedure TCustomADODataSet.InternalFirst;
begin
  if not Recordset.BOF then
  begin
    Recordset.MoveFirst;
    if Recordset.Supports(adMovePrevious) and not Recordset.BOF then
      Recordset.MovePrevious;
  end;
end;

对于大多数(所有)DataSet 衍生品,如果数据集之前已关闭,则在 Open 之后调用 First 是完全多余的。

但是,如果 DataSet 之前已经打开但没有关闭,则 Open 将不执行任何操作(因为 DataSet 已经打开),并且 First 将确保 DataSet 在打开后定位到预期位置(在BOF).