Delphi ADO:使用数据集筛选器定位错误

Delphi ADO : Locate with dataset filter on bug

我有一个简单的查询,returns 以下行:

Name  Value
Peter   1
Peter   2
Peter   3
John    1
John    2

正在应用过滤器:

 ADO.Filter := 'Name="John"';
 ADO.Filtered := True; // Now, its only 2 rows in dataset
 ADO.Locate('Value', 2); 

光标应该指向"John 2",但它指向"Peter 2"(被过滤器过滤掉了)。并找到 returns True.

在Delphi 7、Rad studio XE 6 上试过。似乎这个错误在过去的 15 年里一直存在 有什么解决办法吗?

试试这个:

ADO.Filter := 'Name=' + QuotedStr('John');
ADO.Filtered := True; // Now, its only 2 rows in dataset
ADO.Locate('Value',2,[]);

Locate 函数的第三个参数用于定位选项,我在上面的示例中将其留空。您可以在此处阅读“定位” http://docwiki.embarcadero.com/RADStudio/XE7/en/Using_Locate and here http://docwiki.embarcadero.com/Libraries/XE7/en/Data.DB.TDataSet.Locate

TCustomADODataSet.Locate is that it's internally using Recordset.Clone 的问题,试图在克隆的记录集中定位记录,但未将过滤器设置为克隆的记录集(请参阅 ADODB TCustomADODataSet.LocateRecord)。

来自文档中的备注:

The Filter property of the original Recordset, if any, will not be applied to the clone. Set the Filter property of the new Recordset to filter the results. The simplest way to copy any existing Filter value is to assign it directly, as follows. rsNew.Filter = rsOriginal.Filter The current record of a newly created clone is set to the first record.

我一直在使用我自己的简单 Locate 函数来过滤 ADO 数据集:基本上,存储当前书签,移动到第一条记录并迭代数据集直到找到匹配项。如果找不到匹配项,则恢复以前的书签。
Bellow 是一个非常有限的实现,对我有用(很多待办事项都是一个完美的解决方案):

class function TData.Locate(DataSet: TDataSet; const KeyFields: string;
  const KeyValues: Variant; Options: TLocateOptions): Boolean;
{ a very simple Locate function - todo: TLocateOptions & multiple KeyFields/KeyValues }
var
  BM: TBookmarkStr;
begin
  Result := False;
  if DataSet.IsEmpty then Exit;
  BM := DataSet.Bookmark;
  DataSet.DisableControls;
  try
    DataSet.First;
    while not DataSet.Eof do
    begin
      if DataSet.FieldByName(KeyFields).Value = KeyValues then
      begin
        Result := True;
        Break;
      end;
      DataSet.Next;
    end;
    if not Result then DataSet.Bookmark := BM;
  finally
    DataSet.EnableControls;
  end;
end;

另一种选择是修补 ADODB.pas TCustomADODataSet.LocateRecord 并设置 FLookupCursor.Filter 以匹配当前数据集过滤器。只要您将 ADODB.pas 修补为项目文件夹中的新副本,此选项就可以接受。

另一种选择是使用 TCustomADODataSet.Recordset.Find method (See also: How to use a RecordSet.Find with TADOQuery?).