WebAPI OData $跳过自定义IQueryable double应用

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

[EnableQuery( AllowedQueryOptions = AllowedQueryOptions.Count | AllowedQueryOptions.Filter | AllowedQueryOptions.OrderBy | AllowedQueryOptions.Skip | AllowedQueryOptions.Top)] [ODataRoute] public PageResult Get(ODataQueryOptions queryOptions) { var bars = new QueryableData(_provider); var result = ((IQueryable)queryOptions .ApplyTo(bars, new ODataQuerySettings(new ODataQuerySettings { EnableConstantParameterization = false, EnsureStableOrdering = false }))).ToList(); var count = _provider.Count; return new PageResult(result, null, count); } 

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

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

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

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

在阅读Github问题列表时,我遇到了这篇文章: OData PageResult方法在使用EnableQuery属性#159时忽略count参数 。 似乎是问题的结果是EnableQuery Attribute和参数化的Get构造函数结合使用ODataQueryOptions。 使用这两个意味着您将实现构造函数查询选项,应用查询表达式,然后框架将应用它应用于应用属性的方向上的filter; 因此,重复使用像skip,top和orderby这样的东西。

因为我想自己处理跳过,但我仍然想要EnableQueryAttribute的其他function,我看了一下,发现它是虚拟的。 我创建了一个派生类,然后尝试覆盖ApplyQuery方法。 不幸的是,ODataQueryOptions只在其属性上有私有集,所以我稍稍反省一点。 (感觉很脏但是嘿..)

 public override IQueryable ApplyQuery(IQueryable queryable, ODataQueryOptions queryOptions) { var skipOption = new SkipQueryOption("0", queryOptions.Context); typeof(ODataQueryOptions).GetProperty("Skip").SetValue(queryOptions, skipOption, null); return base.ApplyQuery(queryable, queryOptions); } 

当skip选项现在为0时,它不会在构造响应时应用它,也不再使用“double skip blues”。