C# 什么时候ObjectQuery真的是一个IOrderedQueryable?

C# 什么时候ObjectQuery真的是一个IOrderedQueryable?,c#,linq,entity-framework-4,interface,C#,Linq,Entity Framework 4,Interface,应用于实体框架,扩展方法Select()和OrderBy()都返回一个ObjectQuery,其定义如下: public class ObjectQuery<T> : ObjectQuery, IOrderedQueryable<T>, IQueryable<T>, <... more interfaces> 这给了我一个IQueryable,它是一个ObjectQuery。但它也是一个IOrderedQueryable: var b =

应用于实体框架,扩展方法
Select()
OrderBy()
都返回一个
ObjectQuery
,其定义如下:

public class ObjectQuery<T> : ObjectQuery, IOrderedQueryable<T>,
    IQueryable<T>, <... more interfaces>
这给了我一个
IQueryable
,它是一个
ObjectQuery
。但它也是一个IOrderedQueryable:

var b = query is IOrderedQueryable<Plot>; // True!
var b=query是IOrderedQueryable;//真的!
但仍然:

var query2 = query.ThenBy(p => p.Number); // Does not compile.
// 'IQueryable<Plot>' does not contain a definition for 'ThenBy'
// and no extension method 'ThenBy' ....
var query2=query.ThenBy(p=>p.Number);//不编译。
//“IQueryable”不包含“ThenBy”的定义
//没有扩展方法“ThenBy”。。。。
当我这样做时:

var query2 = ((IOrderedQueryable<Plot>)query).ThenBy(p => p.Number);
var query2=((IOrderedQueryable)查询),然后是by(p=>p.Number);
它进行编译,但给出运行时异常:

类型为“
IQueryable`1[Plot]
”的表达式不能用于方法“
IOrderedQueryable`1[Plot]
”的类型为“
IOrderedQueryable`1[Plot]”的参数,然后使用[Plot,Nullable`1](IOrderedQueryable`1[Plot],Expressions.Expression`1[System.Func`2[Plot,System.Nullable`1[System.Int32]])
'

强制转换已执行(我已检查),但
ThenBy
的参数仍被视为IQueryable(这让我有点困惑)


现在假设某个方法将一个
ObjectQuery
作为
IQueryable
返回给我(比如
Select()
)。如果我想知道对返回的对象调用
ThenBy
是否安全,该怎么办。如果不捕获示例,我如何才能确定
ObjectQuery
是“真”还是“假”
IOrderedQueryable
!(或者也许我有点古怪),如果有什么依据的话,我可能会在许多开发人员的未来变得有用!=)

在您的情况下,simple从MSDN继承,并在继承类中使用要将
m.MethodInfo
SortBy
进行比较的内容覆盖
VisitMethodCall
方法(即,如果您不太挑剔,只需检查名称,如果您想挑剔,请使用反射获取实际的SortBy MethodInfo进行比较)

让我知道您是否需要示例,但老实说,在复制/粘贴ExpressionVisitor之后,您可能不需要超过10行的非表达式树代码;-)


尽管表达式树很有趣,但在这种情况下,简单的解决方案不是使用OrderBy而不是ThenBy吗

  • OrderBy
    IQueryable
    上的扩展,返回一个
    IOrderedQueryable
  • ThenBy
    IOrderedQueryable
    的扩展,返回一个
    IOrderedQueryable
因此,如果您有一个IQueryable(如上面的例子,其中查询是IQueryable),并且希望对其应用初始排序,请使用
OrderBy
ThenBy
仅用于对已排序的查询应用附加排序

如果您有某种LINQ结果,但不确定它是
IQueryable
还是
IOrderedQueryable
并希望对其应用附加筛选,则可以使用以下两种方法:

 static IOrderedQueryable<T, TKey> ApplyAdditionalOrdering<T, TKey>(this IOrderedQueryable<T, TKey> source, Expression<Func<T, TFilter>> orderBy)
        {
            return source.ThenBy(orderBy);
        }
static IOrderedQueryable ApplyAdditionalOrdering(此IOrderedQueryable源,表达式orderBy)
{
返回来源。然后按(订购方);
}

static IOrderedQueryable applyaadditionalordering(此IQueryable源代码,表达式orderBy)
{
返回source.OrderBy(OrderBy);
}

编译器将根据查询对象的编译时类型找出要调用的正确类型。

我建议不要检查具体类型,因为它会将您绑定到查询提供程序,这正是
IQueryable
避免的。一种方法是快速遍历表达式以检查
SortBy()
方法,但我怀疑有人会指出一些更简单的方法。如果没有,请在这里发表评论,我将为您提供遍历树的代码。好luck@Smudge202谢谢有很多地方比表情树更有趣,但如果你无法抗拒。。。但是是的,可能是其他人。@Smudge202顺便说一句,检查具体类型无论如何都不会工作,因为它实现了两个接口。让我困惑的是,普通的思考在这里并没有帮助,因此,如果我真的需要知道的话,也许你建议的更深入的检查是唯一的方法。是的,我认为通过检查具体类型是不可能的——也许是一种拯救恩典?=)祝你好运,进行更深入的检查。我怀疑这可能是通过某种形式的反射实现的,但正如通过表达式树所建议的那样,肯定是可能的。祝你好运,你做到了。你用表达式树病毒感染了我!这是一个可行的解决方案(顺便说一句,方法名为“OrderBy”),尽管它特定于表达式,而且您是对的,这很有趣!到目前为止,我在公园散步:)。虽然这在这里有效,但我也将发布一个问题,用纯C#术语来阐述这个问题。对于感兴趣的人来说:是纯C#问题。这是一个聪明的解决方案。一个缺点是,它不能用于内部和表达式。与此同时,我从未真正需要知道
IQueryable
是否有初始排序。只是我对这个无操作界面感到困惑。
 static IOrderedQueryable<T, TKey> ApplyAdditionalOrdering<T, TKey>(this IOrderedQueryable<T, TKey> source, Expression<Func<T, TFilter>> orderBy)
        {
            return source.ThenBy(orderBy);
        }
static IOrderedQueryable<T, TKey> ApplyAdditionalOrdering<T, TKey>(this IQueryable<T> source, Expression<Func<T, TFilter>> orderBy)
        {
            return source.OrderBy(orderBy);
        }