Delphi TFDMemTable筛选后丢失/清除数据

Delphi TFDMemTable筛选后丢失/清除数据,delphi,filter,firedac,fdmemtable,Delphi,Filter,Firedac,Fdmemtable,我创建了一个具有以下结构的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('D

我创建了一个具有以下结构的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;
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;
嗯。。。当将筛选属性设置为True并返回False时,就会出现问题。RecordCount属性变为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,这段代码可以完美地工作

我认为这只是一个小小的FD怪癖。下面的代码按预期工作,将
Cds\u NaMenu
声明为TFDMemTable(不过如果您可以删除
Cds\u
以避免混淆,那就太好了)

我认为关键的区别在于清除过滤器后调用
.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;

如果您使用的是纯内存表,那么按属性查询记录计数应该不会有任何问题。可能您希望在筛选视图中包含NULLempty值记录,但实际情况并非如此。当有这样的数据集时:

Cds_NaMenu.Append;
Cds_NaMenu.FieldByName('DISPONIBILIDADE').AsInteger := 1;
Cds_NaMenu.Post;
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;
ID|值
1 |空
2  | ''
3 |“一些文本”
并应用如下过滤器:

Cds_NaMenu.Append;
Cds_NaMenu.FieldByName('DISPONIBILIDADE').AsInteger := 1;
Cds_NaMenu.Post;
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;
视图中不应包括空的空的值记录。这里有一个简短的证明:

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;

依赖于数据集记录计数返回有意义值的代码是在自找麻烦。除此之外,正如您所发现的,不同的数据集类型以不同的方式运行。听起来你的实际问题是X/Y问题。如果它是一个纯内存表的设置,那么就不需要“滚动获取”,因为一切都在客户端,所描述的问题不应该发生。@Victoria,我当然意识到不需要滚动,但遇到了很多情况,不仅仅是FireDAC,这样的问题可以通过强制滚动来解决,即使它什么也不做,比如
MoveBy(0)
。顺便说一句,如果我去帮忙,让Alt团队欺骗一个不喜欢Firebird scrolls进入视图的人的名字,我猜对了吗?刚刚应用了一个过滤器,并且必须强制滚动,这难道不更容易阅读,而且只需要先调用就足够了吗?@Frazz:更容易,为什么?我使用了
Locate
,因为这意味着用户不会失去在数据集中的位置。@Victoria。听起来你的猜测不错,我已经猜到你的答案了。我完全同意你的看法!问题是:过滤设置为False后,.RecordCount没有返回到3。