我最近注意到一些奇怪的东西,Entitiy上的导航属性并没有实现IQueryable,而据我所知检索一个单一的实体,然后在导航属性上链接运算符可能会导致许多(每项1个)调用数据库,从生成的代码中,我发现在单个大型查询中有一个带有子查询结果的大型查询(如果可能)。为什么linq中的子导航中的实体的导航属性没有实现IQueryable?
但是我想知道它是如何工作的,因为在子查询中可用的重载与在子查询之外的导航属性上调用的重载相同。 问题1:我的猜测是,即使它在IEnuerable上,而任何调用本身是传递到where的表达式的一部分,它就会被构建到在where和parsed处生成的单个表达式树中,而不是作为单独的表达式因为它本身不是一个表达),这是正确的吗?
问题2:如果#1是正确的,如果你在只能在运行时在委托中进行的表达式外创建代码,这是如何工作的(例如,如果我通过PredicateExprEntityTwo.Compile( ),在q5中,编译时不会编译和失败,因为编译器不知道编译时表达式中func的用法?
问题3:假设我有#1和# 2正确的,这个设计的优点与在那里做表达式有什么关系?我遇到的缺点是,对于业务验证,我想有一组谓词,其中包含业务逻辑,用于过滤相同类型的实体程序中的许多地方,但我可能想要在子查询中使用它们假设#2是正确的,重复使用同一个可能是不可行的?
对不起,如果问题听起来有点混乱,但我只注意到上周我有IEnumerables重载在子查询中调用,但仍然是一个单一的EF查询作为输出,我很好奇这可能是如何工作。
public class Class1
{
void Test()
{
Func<Entity1, bool> PredicateFuncEntityOne = i => i.Id == 2;
Expression<Func<Entity1, bool>> PredicateExprEntityOne = i => i.Id == 2;
Func<Entity2, bool> PredicateFuncEntityTwo = i => i.Id == 2;
Expression<Func<Entity2, bool>> PredicateExprEntityTwo = i => i.Id == 2;
using (var Context = new TestModelContainer())
{
// Works as this expects an expression
var q1 = Context.Entity1Set.Where(PredicateExprEntityOne);
// Works but would call the IEnumerable version
var q2 = Context.Entity1Set.Where(PredicateFuncEntityOne);
// This compiles, any on item.Entity2 expects a func on IEnumerable, not IQueryable overload
var q3 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateFuncEntityTwo));
// This fails for the reason mentioned above
var q4 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo));
// Does this work and if so how is it possible?
var q5 = Context.Entity1Set.Where(item => item.Entity2.Any(PredicateExprEntityTwo.Compile()));
}
}
}
你好,虽然这是安慰它并没有真正回答我的问题,我真的在寻找规范级别的答案,因为我即将围绕它制定一些强大的程序设计决策,同时我可以测试我宁愿有一个清晰的解释,以及whys(特别是因为我建议是反直觉相比,将这些标记为IQueryable,我真的想知道如果我失去了一些东西)。 – 2011-05-09 23:24:24