【问题标题】:How to get an IOrderedQueryable<T> after calling Skip() and Take()?调用 Skip() 和 Take() 后如何获取 IOrderedQueryable<T>?
【发布时间】:2022-01-19 03:12:50
【问题描述】:

我有一个包含ApplyFilter() 方法的分页类,它过滤当前页面的行。由于分页通常只对排序的结果有意义,因此此方法接受并返回 IOrderedQueryable&lt;T&gt;(而不仅仅是 IQueryable&lt;T&gt;)。

我是这样使用的:

var query = DbContext.Items
            .Where(i => i.Value > 0)
            .OrderBy(i => i.SortColumn);

query = pagination.ApplyFilter(query);

但是我的ApplyFilter() 方法有问题。

public IOrderedQueryable<T> ApplyFilter<T>(IOrderedQueryable<T> query)
{
    return query.Skip((CurrentPage - 1) * PageSize).Take(PageSize);
}

Skip()Take() 方法都返回一个IQueryable&lt;T&gt;,所以我收到一个错误,返回值无法从IQueryable&lt;T&gt; 转换为IOrderedQueryable&lt;T&gt;

如何在使用Skip()Take() 的同时仍然拥有IOrderedQueryable&lt;T&gt;

【问题讨论】:

  • 查询没有应用ThenBy 的顺序。将其作为 IOrderedQueryable 是没有意义的。该接口存在的全部意义在于确保 ThenBy 仅可用于直接响应 OrderBy 调用。
  • @Servy:是的,但这会很好。你可以从我调用它的代码中看到,重载也返回 IOrderedQueryable&lt;T&gt; 会很方便。
  • 尝试声明查询已订购的缺点似乎明显超过了在不再需要使用的已订购查询上简单地调用 AsQueryable 的成本ThenBy (或者简单地使用一个新变量,这通常是更好的选择,变量使用起来并不昂贵)。为手头的问题使用正确的解决方案。将有序查询视为一般查询很好,将无序查询视为已订购只会给自己带来麻烦。
  • @Servy:很好。太糟糕了AsQueryable() 必须分配额外的对象。我不认为这是最小的开销。
  • 您认为它将分配哪些对象?它的开销大大比您想出的将查询变成有序可查询的任何可能的实现都少(这永远不可能避免代码中不会在运行时抛出的任何分配)。 AsQueryable 除了改变对象的编译时类型之外什么也没做。

标签: c# entity-framework entity-framework-core iqueryable .net-6.0


【解决方案1】:

你可以做一些俗气的事情,比如

public IOrderedQueryable<T> ApplyFilter<T>(IOrderedQueryable<T> query)
{
    return query.Skip((CurrentPage - 1) * PageSize).Take(PageSize).OrderBy(i=>1);
}

至少对于 SQL Server,codegen 足够聪明,可以忽略 OrderBy。

或者将返回类型改为IQueryable&lt;T&gt;,不要复用查询变量:

var q = db.Set<User>().OrderBy(u => u.id);
var q2 = ApplyFilter(q);

或者将参数和返回类型更改为IQueryable&lt;T&gt;,如果有人通过了不是IOrderedQueryable&lt;T&gt;的参数,则抛出ArgumentException

public IQueryable<T> ApplyFilter<T>(IQueryable<T> query)
{
    if (query is IOrderedQueryable<T> oq )
    {
        return oq.Skip((CurrentPage - 1) * PageSize).Take(PageSize);
    }
    else
    {
        throw new ArgumentException("Query must be IOrderdQueryable<T>");
    }
}

【讨论】:

  • 是的,那个 hack 相当难看。太糟糕了,您不能以某种方式简单地将IQueryable&lt;T&gt; 转换为IOrderedQueryable&lt;T&gt;。 (不附加其他操作。)
猜你喜欢
  • 2021-08-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-03
  • 2018-02-03
  • 1970-01-01
  • 2015-04-28
相关资源
最近更新 更多