【问题标题】:Is there a limit for TClientDataSet filter, or is it a bug?TClientDataSet 过滤器是否有限制,还是一个错误?
【发布时间】:2025-11-23 00:10:02
【问题描述】:

我使用TClientDataSet 作为内存表,并且必须应用具有很多条件的过滤器。

例如,对于 400 个OR 条件,我在尝试启用过滤器时遇到访问冲突。

模块“midas.dll”中地址 4DAEDC76 的访问冲突。读取地址 00000034。

这里发生异常:

procedure TCustomClientDataSet.AddExprFilter(const Expr: Widestring; Options: TFilterOptions); 
begin 
  if FExprFilter <> nil then FDSCursor.DropFilter(FExprFilter); 
  if Expr <> '' then 
  with TExprParser.Create(Self, Expr, Options, [poExtSyntax], '', nil, FieldTypeMap, True) do 
    try 
      CheckProviderEOF; 
      Check(FDSCursor.AddFilter(FilterData, DataSize, FExprFilter)); // ** AV HERE
    finally 
      Free; 
    end; 
end; 

这是组件上的错误还是 midas.dll 的限制? 我在这些 midas 版本上测试了这种行为:>= 15 和

我正在使用 Delphi XE。 示例代码:

procedure TForm41.Button1Click(Sender: TObject);
var
  I: Integer;
  FilterStr: string;
begin
  FilterStr := '(vehicleId = -1)';
  //It is just an example, the original code I can have any integer number.
  for I := 0 to 400 do //If I change the limit value to 40 for example, it works. 
    FilterStr := FilterStr + ' or (vehicleId = ' + IntToStr(I) + ')';

  ClientDataSet1.Filter := FilterStr;
  ClientDataSet1.Filtered := True;
  ClientDataSet1.CreateDataSet; //Error here
end;

我已经尝试过使用 IN 语句,但我得到了同样的错误。

我没有在互联网上找到关于这种情况的参考资料。

【问题讨论】:

  • 你得到什么异常?为什么您可能需要添加 400 OR 条件?如果你不得不这样做,那你就做错了。如果您需要过滤那么多,请在主数据集中或使用TClientDataSet.OnFilterRecord 事件进行。
  • 遗留代码 Ken White,如果不进行大量修改,我可以轻松更改任何内容。这是一个权限过滤器,用户可以看到 400 辆车。
  • 您可以使用OnFilterRecord,无需进行重大修改。你还没有指出你得到了什么异常。您看到了什么确切异常消息?
  • 我一般访问冲突,我跟踪代码:它发生在这一行:Check(FDSCursor.AddFilter(FilterData, DataSize, FExprFilter));即:procedure TCustomClientDataSet.AddExprFilter(const Expr: Widestring; Options: TFilterOptions);如果 FExprFilter nil 则开始 FDSCursor.DropFilter(FExprFilter); if Expr '' then with TExprParser.Create(Self, Expr, Options, [poExtSyntax], '', nil, FieldTypeMap, True) 试试 CheckProviderEOF; Check(FDSCursor.AddFilter(FilterData, DataSize, FExprFilter));终于免费了;结尾;结束;
  • 我相信我从未见过除了General Access Violation 之外什么都不说的Delphi 异常。对于第三次,您看到的确切错误消息是什么?不是我看到类似的东西,而是确切的错误消息,包括内存地址。

标签: delphi delphi-xe datasnap tclientdataset


【解决方案1】:

我可以重现此错误,包括 Delphi Seattle 中的“读取地址 00000034”。 当过滤器表达式中有超过 280 个术语时会发生这种情况。它是 显然是midas限制。您需要一种更好的方法来翻译您的问题域 达到您的过滤器所需的效果。

如果您可以在代码中评估您的条件,那么我要做的就是添加 一个布尔 fkInternalCalc 字段到 CDS 并将其设置为 True of False 取决于结果。然后,过滤数据集是一件简单的事情 根据布尔值应用过滤器。

【讨论】:

  • 谢谢马丁娜。你在哪里找到 valeu 280 的?你知道内存表吗?谢谢
  • 通过实验:注意到我得到了 300 个术语的异常,但不是 200 个,我在两者之间进行了二进制搜索。还有许多其他的内存表,但我总是使用 CDS 来处理这类东西,尽管它偶尔会有缺点。
  • 我找到了其他内存表,但都是基于TDataSet的。我发现了其他一些,但我不知道它的实现,因为它们不是免费的。
  • 严格来说不是内存数据库,但你试过 Sqlite 吗?最近的 Delphi 版本通过 FireDAC 对它提供了很好的支持,但您可能会发现在 XE 中的 DBExpress 中对它提供了支持。
  • @RodrigoFariasRezino 虽然这只是一个临时(并且仍然不优雅)的解决方案,但您始终可以通过使用包含过滤器(即:包含选定的 ID)用于少于 200 个项目和排他过滤器(即:排除未选定的 ID)用于超过 200 个项目。
最近更新 更多