You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用自动生成OData Client时,CreateQuery<T>未应用谓词求助

问题描述

我正在使用自动生成的OData Client,尝试创建一个通用客户端类,希望通过谓词筛选获取数据。编写的代码如下:

public T Get<T>(Func<T, bool> predicate)
{
  var entityName = GetEntitySetName<T>();
  var query = _d365Context.CreateQuery<T>(entityName);
  return query.Where(predicate).FirstOrDefault();
}

private static string GetEntitySetName<T>()
{
  var originalEntitySetName = typeof(T).GetCustomAttributes(typeof(EntitySetAttribute), true).Cast<EntitySetAttribute>().SingleOrDefault()?.EntitySet;
  return originalEntitySetName;
}

但这段代码会读取全部数据,并未应用谓词筛选。我已尝试过这些方案:

  • 知道query有AddQueryOption方法,但不想使用;
  • 可以直接使用context.EntityName,但这会硬编码实体名。

我的问题是:能否实现我想要的功能?有没有可用的现有库?
注:不想使用Simple.Odata.Client。
另外我有一个思路:解析谓词并用于AddQueryOption(该方法接收字符串名称和对象值),但我对Func经验不足,不确定是否可行。

解决方案

为什么当前代码会全量读取数据

你用的Func<T, bool>是LINQ to Objects的委托,它会把OData返回的所有数据拉到本地后再执行筛选,而不是把筛选条件转换成OData的$filter语句发送到服务端,这就是导致全量读取的核心原因。要实现服务端筛选,必须用表达式树Expression<Func<T, bool>>替代普通委托。

实现通用服务端筛选的最优方案

  1. 改用Expression<Func<T, bool>>作为参数
    自动生成的OData Client上下文的CreateQuery<T>返回的是IQueryable<T>,它原生支持表达式树解析,可以把Expression直接转换成OData的$filter参数发送到服务端。修改后的代码如下:
public T Get<T>(Expression<Func<T, bool>> predicate)
{
    var entityName = GetEntitySetName<T>();
    var query = _d365Context.CreateQuery<T>(entityName);
    return query.Where(predicate).FirstOrDefault();
}

private static string GetEntitySetName<T>()
{
    var originalEntitySetName = typeof(T).GetCustomAttributes(typeof(EntitySetAttribute), true)
        .Cast<EntitySetAttribute>()
        .SingleOrDefault()?.EntitySet;
    return originalEntitySetName;
}

这个方案无需额外库,直接利用OData Client的原生能力,既实现了服务端筛选,又保持了实体名的自动获取,完全避免硬编码。

  1. 关于你提到的解析Func的思路
    解析Func<T, bool>转成AddQueryOption参数的思路可行,但完全没必要——因为Func是编译后的委托,没有表达式树的结构信息,解析需要通过IL反编译等复杂手段,远不如直接用Expression<Func<T, bool>>简洁高效。

  2. 可选的辅助库(无需Simple.OData.Client)
    如果需要构建更复杂的OData查询,可以考虑:

  • Microsoft.OData.Client:就是你当前使用的自动生成客户端的基础库,本身已支持表达式树转OData查询,无需额外引入;
  • ODataQueryBuilder:轻量的OData查询构建库,可辅助生成复杂的$filter语句,但对你的场景来说,原生表达式树方案已经足够满足需求。

关键注意点

  • 确保自动生成的实体类上正确标记了EntitySetAttribute,否则GetEntitySetName<T>可能返回null,导致查询失败;
  • 并非所有.NET表达式都能被OData Client转换成有效的$filter语句,比如自定义方法调用、过于复杂的条件嵌套可能无法解析,需要遵循OData协议支持的运算符和函数规范。

内容的提问来源于stack exchange,提问作者Manish

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 19:47:22