簡體   English   中英

TFDMemTable過濾后丟失/清除數據

[英]TFDMemTable lost/clearing data after filtering

我創建了具有以下結構的FDMemTable:

Cds_NaMenu := TFDMemTable.Create(nil);
Cds_NaMenu.FieldDefs.Add('ID', ftInteger);
Cds_NaMenu.FieldDefs.Add('MN_TELA_CODIGO', ftInteger);
Cds_NaMenu.FieldDefs.Add('MN_MENU_PESQUISA', ftString, 500);
Cds_NaMenu.FieldDefs.Add('DISPONIBILIDADE', ftInteger);
Cds_NaMenu.IndexDefs.Add('Ordem', 'MN_TELA_CODIGO', []);
Cds_NaMenu.CreateDataSet;
Cds_NaMenu.LogChanges := False;
Cds_NaMenu.IndexName := 'Ordem';

我將數據放入TFDMemTable中,如下所示:

Cds_NaMenu.Append;
Cds_NaMenu.FieldByName('DISPONIBILIDADE').AsInteger := 1;
Cds_NaMenu.Post;

好吧...將已過濾的屬性設置為True並返回False時,就會出現問題。 RecordCount屬性變為0;否則為0。 即使我使用saveToFile過程也找不到任何數據。 顯然,數據丟失了。

_recCount := Cds_NaMenu.RecordCount; // Result = 867;
Cds_NaMenu.Filter := 'DISPONIBILIDADE=1 AND MN_MENU_PESQUISA like ' + QuotedStr('%' + sTexto + '%');
Cds_NaMenu.Filtered := True;
_recCount := Cds_NaMenu.RecordCount; // Result = 0;
Cds_NaMenu.Filtered := False;
Cds_NaMenu.Filter := '';
_recCount := Cds_NaMenu.RecordCount; // Result = 0;

PS:使用ClientDataSet,此代碼可以完美運行

如果您使用的是純內存表,則通過RecordCount屬性查詢記錄數應該沒有任何問題。 也許您希望在使用過濾器值LIKE'%%'時在過濾視圖中包含NULL值記錄,但事實並非如此。 當具有這樣的數據集時:

ID | Value
1  | NULL
2  | ''
3  | 'Some text'

並應用這樣的過濾器:

var
  S: string;
begin
  S := '';
  FDMemTable.Filtered := False;
  FDMemTable.Filter := 'Value LIKE ' + QuotedStr('%' + S + '%');
  FDMemTable.Filtered := True;
  { ← FDMemTable.RecordCount should be 1 here for the above dataset }
end;

值和NULL值記錄不應包含在視圖中。 這是一個簡短的證明:

var
  S: string;
  MemTable: TFDMemTable;
begin
  MemTable := TFDMemTable.Create(nil);
  try
    MemTable.FieldDefs.Add('ID', ftInteger);
    MemTable.FieldDefs.Add('Value', ftString, 500);
    MemTable.IndexDefs.Add('PK_ID', 'ID', [ixPrimary]);
    MemTable.CreateDataSet;

    MemTable.AppendRecord([1, NULL]);
    MemTable.AppendRecord([2, '']);
    MemTable.AppendRecord([3, 'Some text']);

    S := '';
    MemTable.Filtered := False;
    MemTable.Filter := 'Value LIKE ' + QuotedStr('%' + S + '%');

    ShowMessage(Format('Total count: %d', [MemTable.RecordCount])); { ← should be 3 }
    MemTable.Filtered := True;
    ShowMessage(Format('Filtered count: %d', [MemTable.RecordCount])); { ← should be 1 }
    MemTable.Filtered := False;
    ShowMessage(Format('Total count: %d', [MemTable.RecordCount])); { ← should be 3 }
  finally
    MemTable.Free;
  end;
end;

我認為這只是次要的FD怪癖。 下面的代碼按預期方式工作,並且將Cds_NaMenu聲明為TFDMemTable(盡管如果可以刪除Cds_以避免混淆,效果會很好)。

我認為,關鍵的區別在於清除過濾器后對.Locate的調用。 我把它放在這里的原因是因為它導致數據集滾動,並且我想以此作為結果重新計算其RecordCount 可能導致滾動的任何其他操作也將具有相同的效果,即使是MoveBy(0) -嘗試一下。

procedure TForm1.FormCreate(Sender: TObject);
var
  _recCount : Integer;
  ID : Integer;
  sTexto : String;
begin
  sTexto := 'xxx';  // added

  Cds_NaMenu.FieldDefs.Add('ID', ftInteger);
  Cds_NaMenu.FieldDefs.Add('MN_TELA_CODIGO', ftInteger);
  Cds_NaMenu.FieldDefs.Add('MN_MENU_PESQUISA', ftString, 500);
  Cds_NaMenu.FieldDefs.Add('DISPONIBILIDADE', ftInteger);
  Cds_NaMenu.IndexDefs.Add('Ordem', 'MN_TELA_CODIGO', []);
  Cds_NaMenu.CreateDataSet;
  Cds_NaMenu.LogChanges := False;
  Cds_NaMenu.IndexName := 'Ordem';


  Cds_NaMenu.Append;
  Cds_NaMenu.FieldByName('ID').AsInteger := 666;  // added
  Cds_NaMenu.FieldByName('DISPONIBILIDADE').AsInteger := 1;
  Cds_NaMenu.Post;


  _recCount := Cds_NaMenu.RecordCount; // Result = 1

  ID := Cds_NaMenu.FieldByName('ID').AsInteger;  // added

  Cds_NaMenu.Filter := 'DISPONIBILIDADE=1 AND MN_MENU_PESQUISA like ' + QuotedStr('%' + sTexto + '%');
  Cds_NaMenu.Filtered := True;
  _recCount := Cds_NaMenu.RecordCount; // Result = 0;
  Cds_NaMenu.Filtered := False;
  Cds_NaMenu.Filter := '';

  // Now force the dataset to scroll
  if Cds_NaMenu.Locate('ID', ID, []) then;  // added
  _recCount := Cds_NaMenu.RecordCount; // Result = 1;
  Caption := IntToStr(_recCount);  // added
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM