Delphi ADO:找到bug上的数据集过滤器

时间:2015-01-30 08:13:11

标签: delphi filter ado locate

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

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”(由滤镜过滤掉)。并且定位返回True。

尝试使用Delphi 7,Rad studio XE 6.看来这个错误在过去的15年里一直存在 任何解决方案?

2 个答案:

答案 0 :(得分:6)

TCustomADODataSet.Locate的问题在于它在内部使用Recordset.Clone并尝试在克隆记录集中找到记录,而不将过滤器设置为克隆记录集(请参阅ADODB TCustomADODataSet.LocateRecord)。

来自文档中的备注:

  

原始Recordset的Filter属性(如果有)不会   应用于克隆。设置新Recordset的Filter属性   过滤结果。复制任何现有Filter的最简单方法   value是直接赋值,如下所示。 rsNew.Filter =   rsOriginal.Filter设置新创建的克隆的当前记录   到了第一张唱片。

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

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方法(另请参阅:How to use a RecordSet.Find with TADOQuery?)。

答案 1 :(得分:0)

试试这个:

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_Locatehttp://docwiki.embarcadero.com/Libraries/XE7/en/Data.DB.TDataSet.Locate