WebAPI OData $Skip 自定义 IQueryable 双重应用

2024-02-17

我已经实现了一个通过 WebAPI OData 端点公开的自定义 IQueryable。控制器的 Get() 的结构相当标准:

[EnableQuery(
    AllowedQueryOptions = AllowedQueryOptions.Count
                          | AllowedQueryOptions.Filter
                          | AllowedQueryOptions.OrderBy
                          | AllowedQueryOptions.Skip
                          | AllowedQueryOptions.Top)]
[ODataRoute]
public PageResult<Foo> Get(ODataQueryOptions<Foo> queryOptions)
{

    var bars = new QueryableData<Foo>(_provider);

    var result = ((IQueryable<Foo>)queryOptions
        .ApplyTo(bars,
            new ODataQuerySettings(new ODataQuerySettings { EnableConstantParameterization = false, EnsureStableOrdering = false }))).ToList();
    var count = _provider.Count;
    return new PageResult<Foo>(result, null, count);
}

我看到的奇怪行为是,在返回 PageResult 后应用查询字符串中的 OData $Skip。例如:

  • 如果查询字符串包含 ?$top=10&$skip=10 则不会返回结果。
  • 如果查询字符串包含 ?&top=12&skip=10,将返回 (2) 个结果。

我想要做的是防止框架将 Skip 应用到我的结果集,因为查询提供程序已经实现了 Skip。是否可以设置 ODataQuerySettings 来防止这种双重应用跳过?

编辑: 经过进一步调查,当我按预期从查询字符串中删除 $count=true 时,跳过(和顶部)函数。这让我相信我实现 $count=true 的方法是不正确的。从我的调试会话来看,当 $count=true 位于查询选项中时,可查询对象将表达式树应用到它两次,一次返回类型为 long,然后再次没有包装 countlong 表达式。我尝试在第一遍返回计数,然后在第二遍返回正确的可查询数,但这会导致跳过表达式的延迟应用。我在这里似乎缺少一些非常基本的东西。


在阅读 Github 问题列表时,我发现了这篇文章:使用 EnableQuery 属性时 OData PageResult 方法忽略计数参数 #159 https://github.com/OData/WebApi/issues/159。问题似乎在于 EnableQuery 属性和采用 ODataQueryOptions 的参数化 Get 构造函数的组合。使用两者意味着您将实现构造函数查询选项,应用查询表达式,然后框架将根据所应用的属性应用它可以使用的过滤器;因此双重应用诸如skip、top和orderby之类的东西。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WebAPI OData $Skip 自定义 IQueryable 双重应用 的相关文章

随机推荐