Val*_*riy 3 delphi ado filter locate
我有简单的查询,它返回以下行:
Name Value
Peter 1
Peter 2
Peter 3
John 1
John 2
Run Code Online (Sandbox Code Playgroud)
应用过滤器:
ADO.Filter := 'Name="John"';
ADO.Filtered := True; // Now, its only 2 rows in dataset
ADO.Locate('Value', 2);
Run Code Online (Sandbox Code Playgroud)
光标应指向"John 2",但它指向"Peter 2"(由滤镜过滤掉).并且定位返回True.
尝试使用Delphi 7,Rad studio XE 6.看来这个错误是在过去的15年里存在的任何解决方案?
问题TCustomADODataSet.Locate在于它在内部使用Recordset.Clone并尝试在克隆记录集中查找记录,而不将过滤器设置为克隆记录集(请参阅ADODB TCustomADODataSet.LocateRecord).
来自文档中的备注:
原始Recordset的Filter属性(如果有)将不会应用于克隆.设置新Recordset的Filter属性以过滤结果.复制任何现有Filter值的最简单方法是直接分配它,如下所示.rsNew.Filter = rsOriginal.Filter将新创建的克隆的当前记录设置为第一个记录.
我一直在使用我自己的简单Locate函数来过滤ADO DataSet:基本上,存储当前书签,移动到第一个记录并迭代DataSet直到找到匹配.如果找不到匹配项,则恢复上一个书签.
Bellow是一个非常有限的实现,对我有用(很多todo tho的完美解决方案):
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;
Run Code Online (Sandbox Code Playgroud)
另一个选项是修补ADODB.pas TCustomADODataSet.LocateRecord并将其设置FLookupCursor.Filter为与当前数据集过滤器匹配.只要将ADODB.pas修补为项目文件夹中的新副本,就可以使用此选项.
另一种选择是使用TCustomADODataSet.Recordset.Find方法(另请参阅:如何使用TADOQuery使用RecordSet.Find?).