【问题标题】:How can I tell if an IQueryable is an IOrderedQueryable?如何判断 IQueryable 是否为 IOrderedQueryable?
【发布时间】:2011-02-21 21:22:39
【问题描述】:

我有一个 IQueryable。我没有调用 OrderBy 或以其他方式对其进行任何处理。

如果我这样做:

// for some reason, isItOrdered is always true
var isItOrdered = myQueryable is IOrderedQueryable<T>

为什么总是这样? (似乎不应该这样。)而且,更重要的是,我如何判断 IQueryable 是否已经被订购? (即是真正的 IOrderedQueryable)

我希望能够做类似的事情:

if (myQueryable is IOrderedQueryable<T>)
  myQueryable = myQueryable.ThenBy(...);
else
  myQueryable = myQueryable.OrderBy(...);

【问题讨论】:

标签: c# linq


【解决方案1】:

您尚未展示创建可查询对象的原因,但也许它以某种方式自然排序?

你所拥有的确实检查它是否真的是IOrderedQueryable&lt;T&gt; - 我怀疑这只是你的查询提供程序总是提供了一个有序的可查询,即使顺序不明显。

编辑:好的,你可以试试别的方法:

if (typeof(IOrderedQueryable<T>).IsAssignableFrom(myQueryable.Expression.Type))

...或者一般情况下,打印出myQueryable.Expression.Type 看看它是什么样子的。

【讨论】:

  • 问题是当我尝试使用 ThenBy 时遇到了一个令人讨厌的异常。它是这样的: System.Linq.IQueryable 类型的表达式不能用于 IOrderedQueryable 方法的 IOrderedQueryable 类型的参数 ThenBy ....
  • Entity Framework 的问题在于 EF DbSet&lt;T&gt; 继承自 DbQuery&lt;T&gt;,而 DbQuery&lt;T&gt; 本身实现了 IOrderedQueryable&lt;T&gt;!因此,如果 myQueryable 是一个 EF 查询但根本没有排序,您的语句总是返回 true
  • @MassoodKhaari: Ick - 这太可怕了:(我的回答当然仍然回答了这个问题 - 它只是意味着这不是一个 有用 的问题要问......
  • 但我认为这是问题的确切来源。他有一个IQueryable 对象,根本没有调用OrderBy。但是语句myQueryable is IOrderedQueryable&lt;T&gt; 总是返回true。这意味着可以创建一个确实未排序的IOrderedQueryable&lt;T&gt; 对象。另一个含义是 EF 确实做了这么奇怪的事情。 (它在内部检查查询对象表达式,以检测它是否通过调用OrderByOrderByDescending 进行排序。)
  • 它对我很有帮助,但对于我的所有情况仍然不够。当 EF6 DbSet 仅被 Include(没有 Where)触及时,测试 IsAssignableFrom 仍会在未排序的查询上返回 true。为了解决这个问题,我不得不将测试更改为:typeof(IOrderedQueryable&lt;T&gt;).IsAssignableFrom(query.Expression.Type) &amp;&amp; query.Expression.Type != typeof(System.Data.Entity.Core.Objects.ObjectQuery&lt;T&gt;)。更丑。
【解决方案2】:

这似乎有效

if (query.Expression.Type == typeof(IOrderedQueryable<T>))
    myQueryable = myQueryable.ThenBy(...);
else
    myQueryable = myQueryable.OrderBy(...);

【讨论】:

    【解决方案3】:

    一些IQueryable 实现为IOrderedQueryable&lt;T&gt; 重复使用相同的类。

    除非您知道如何它是如何订购的,否则检查它是否真的已经订购并没有多大意义,否则当您致电ThenBy() 时,您可能会通过完全相同的属性订购。

    此外,如果 myQueryable 是对 IQueryable 的引用,则您不能在 Queryable.ThenBy() 上调用它——您必须先进行转换:

    if (myQueryable is IOrderedQueryable<T>)
       myQueryable = ((IOrderedQueryable<T>) myQueryable).ThenBy(...);
    

    【讨论】:

    • 是的。但就我而言,如果我有多余的订单,这不是问题。正如我在对 Jon Skeet 的评论中提到的那样,我遇到了一个疯狂的例外。
    • 是的——我会先施放它。我仍然得到异常。
    • @MarkCidade 我遇到了同样的问题,使用您在上面发布的代码。 @Pedro 您是否有机会使用 Entity Framework 7? var myQueryable = context.Table.Select(x =&gt; x);var myQueryable = from x in context.Table select x 都返回 IOrderedQueryable,但调用 ThenBy() 会在运行时引发 ArgumentException。
    • 异常说:附加信息:方法'System.Linq.IOrderedQueryable1[Models.Table] ThenBy[Table,String](System.Linq.IOrderedQueryable1[Models.Table]'System.Linq.IQueryable1[Models.Table]' cannot be used for parameter of type 'System.Linq.IOrderedQueryable1[Models.Table]'类型的表达式], System.Linq.Expressions.Expression1[System.Func2[Models.Table,System.String]])'
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-26
    • 2014-04-12
    相关资源
    最近更新 更多