TClientDataSet遍历和删除记录导致某些记录在while循环中遍历两次(如果使用Index)

She*_*hew 3 delphi tclientdataset while-loop delete-row delphi-xe4

我有以下代码遍历所有数据TClientDataSet,我的目的是删除除以外的所有记录DocKey=20381.

但是使用以下代码,您将注意到DocKey = 20381被遍历两次的记录(遍历时间= 6,假设为5次,因为我们只有5条记录TClientDataSet).

如果我们启用此行 - > D.IndexFieldNames := 'DocKey',则数据将正确遍历.我可以知道这是一个Delphi漏洞吗?或者有什么办法解决这个除了使用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;
Run Code Online (Sandbox Code Playgroud)

Sir*_*ufo 5

此行为与设计和记录一致

如果删除的记录是数据集中的最后一条记录,则前一条记录将成为当前记录.

20157 -> delete
20162 -> delete
20381 -> next
20372 -> delete
20377 -> delete (last record -> goto previous record -> not eof)

有了这条线

D.IndexFieldNames := 'DocKey';
Run Code Online (Sandbox Code Playgroud)

不被删除的记录将成为在数据集中的最后记录,因此没有删除最后一条记录,而不是该行为.

20157 -> delete
20162 -> delete
20372 -> delete
20377 -> delete
20381 -> next

UPDATE

如果你想避免这种情况 - 由于我不知道或我无法想象的任何原因 - 只需检查,如果电流RecNo减少了.

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;
Run Code Online (Sandbox Code Playgroud)