【发布时间】:2012-01-26 20:50:36
【问题描述】:
应用于实体框架,扩展方法Select()和OrderBy()都返回一个ObjectQuery,定义为:
public class ObjectQuery<T> : ObjectQuery, IOrderedQueryable<T>,
IQueryable<T>, <... more interfaces>
Select() 的返回类型为IQueryable<T>,OrderBy 的返回类型为IOrderedQueryable<T>。所以你可以说两者都返回相同的类型但在不同的包装器中。幸运的是,因为现在我们可以在调用OrderBy 之后应用ThenBy。
现在是我的问题。
假设我有这个:
var query = context.Plots.Where(p => p.TrialId == 21);
这给了我一个IQueryable<Plot>,这是一个ObjectQuery<Plot>。但它也是一个 IOrderedQueryable:
var b = query is IOrderedQueryable<Plot>; // True!
但还是:
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 = ((IOrderedQueryable<Plot>)query).ThenBy(p => p.Number);
它可以编译,但会出现运行时异常:
“
IQueryable`1[Plot]”类型的表达式不能用于“IOrderedQueryable`1[Plot] ThenBy[Plot,Nullable`1](IOrderedQueryable`1[Plot], Expressions.Expression`1[System.Func`2[Plot,System.Nullable`1[System.Int32]]])”方法的'IOrderedQueryable`1[Plot]'类型参数
执行了强制转换(我检查了),但ThenBy 的参数仍然被视为 IQueryable(这让我有点困惑)。
现在假设某个方法将ObjectQuery<Plot> 作为IQueryable<Plot> 返回给我(例如Select())。如果我想知道在返回的对象上调用ThenBy 是否安全怎么办。如何在不捕获异常的情况下判断 ObjectQuery 是“真实”还是“假”IOrderedQueryable?
【问题讨论】:
-
我建议不要检查具体类型,因为它会将您绑定到您的查询提供程序,这正是
IQueryable避免的。一种方法是快速浏览表达式以检查SortBy()方法,但我怀疑有人会指出一些更容易的东西。如果没有,请在此处发表评论,我将为您提供遍历树的代码。祝你好运 -
@Smudge202 谢谢。有很多地方比表情树更有趣,但如果你无法抗拒……但是,是的,也许是其他人。
-
@Smudge202 顺便说一句,检查具体类型无论如何都不起作用,因为它实现了两个接口。让我感到困惑的是,普通的反射在这里没有帮助,所以如果我真的需要知道的话,可能按照你的建议进行更深入的检查是唯一的方法。
-
是的,我认为通过检查具体类型是不可能的——也许是一种节省? =) 祝你好运进行更深入的检查。我怀疑通过某种形式的反射可能是可能的,但通过表达式树的建议绝对可能。祝你好运。
标签: c# linq entity-framework-4 interface