Delphi TClientDataSet&;删除记录会导致某些记录在while循环中被遍历两次(如果使用索引)
我有以下代码遍历Delphi TClientDataSet&;删除记录会导致某些记录在while循环中被遍历两次(如果使用索引),delphi,while-loop,delphi-xe4,delete-row,tclientdataset,Delphi,While Loop,Delphi Xe4,Delete Row,Tclientdataset,我有以下代码遍历TClientDataSet中的所有数据,目的是删除除DocKey=20381之外的所有记录 但在下面的代码中,您会注意到DocKey=20381的记录被遍历了两次(遍历次数=6,假设是5次,因为我们在TClientDataSet中只有5条记录) 如果我们启用此行->D.IndexFieldNames:='docky',则数据将正确遍历。我可以知道这是Delphi的bug吗?或者除了使用IndexFieldNames之外,还有什么方法可以解决这个问题 var D: TClie
TClientDataSet
中的所有数据,目的是删除除DocKey=20381
之外的所有记录
但在下面的代码中,您会注意到DocKey=20381的记录被遍历了两次(遍历次数=6,假设是5次,因为我们在TClientDataSet
中只有5条记录)
如果我们启用此行->D.IndexFieldNames:='docky'
,则数据将正确遍历。我可以知道这是Delphi的bug吗?或者除了使用IndexFieldNames
之外,还有什么方法可以解决这个问题
var
D: TClientDataSet;
begin
D := TClientDataSet.Create(Self);
with D do begin
FieldDefs.Add('DocKey', ftInteger);
CreateDataSet;
AppendRecord([20157]);
AppendRecord([20162]);
AppendRecord([20381]);
AppendRecord([20372]);
AppendRecord([20377]);
end;
// D.IndexFieldNames := 'DocKey';
D.First;
while not D.Eof do begin
if D.Fields[0].AsInteger = 20381 then
D.Next
else
D.Delete;
end;
end;
此行为符合设计和规范要求 如果删除的记录是数据集中的最后一条记录,则前一条记录将成为当前记录 不被删除的记录将成为数据集中的最后一条记录,因此在最后一条记录上不存在删除,而不是该行为 20157 -> delete 20162 -> delete 20372 -> delete 20377 -> delete 20381 -> next
谢谢你的回复。是因为编写for循环代码的方法不正确,还是为了避免出现问题,有更好的编写方法?我是否应该首先将书签添加到TList(用于删除那些记录)中,而不是直接调用TClientDataSet。在for循环中删除,然后根据TList删除记录。为什么这是一个问题?我实际上希望数据集像20377->Delete(last record->next(no more record)->eof这样遍历下一条记录但是你的期望是唯一的问题吗?它只发生一次,所有记录都按预期删除。我没有得到真正的问题谢谢你的更新。我有一些代码遍历数据集来执行算术计算,每个记录只遍历一次而不是两次,以避免错误的计算。同时,如果详细数据集.recordcount=0(主数据集和详细数据集链接),则删除不需要的主记录
D.IndexFieldNames := 'DocKey';
20157 -> delete
20162 -> delete
20372 -> delete
20377 -> delete
20381 -> next
var
D: TClientDataSet;
LRecNo : Integer;
begin
D := TClientDataSet.Create(Self);
with D do begin
FieldDefs.Add('DocKey', ftInteger);
CreateDataSet;
AppendRecord([20157]);
AppendRecord([20162]);
AppendRecord([20381]);
AppendRecord([20372]);
AppendRecord([20377]);
end;
// D.IndexFieldNames := 'DocKey';
D.First;
while not D.Eof do
begin
LRecNo := D.RecNo;
if D.Fields[0].AsInteger = 20381 then
D.Next
else
D.Delete;
if LRecNo > D.RecNo then
Break;
end;
end;