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?).
我有一个简单的查询,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?).