考虑以下功能:
IQueryable<Bar> foo(IEnumerable<IQueryable<Bar>> sources)
{
return
from source in sources.AsQueryable()
from bar in source
where bar.Xzy == 123
select bar;
}
直观地说,我希望这可以执行&#34; from ... where ... select&#34;在每个来源的上下文中表达。但是,我相信它只会在...中执行&#34;来自...&#34;反对来源的部分,而是执行&#34;其中... select&#34;部分作为LINQ到对象查询。最终结果是SomeTable的所有行都将从每个源中检索,而不是仅仅匹配&#34;其中&#34;条件。
乍一看,我的猜测是,这是因为对SelectMany的调用会导致&#34;来源&#34;要隐式转换为IEnumerable&lt; Bar&gt;的表达式。我不确定实现是什么样的,但是它接受Func&lt; S,IQueryable&lt; R&gt;&gt;是不合理的了。相反,所以where ... select表达式被传递给IQueryable提供者?
答案 0 :(得分:1)
我认为这取决于编译器如何解释您的查询。实际上你的查询是什么就是这样的(一个严格的从左到右的解析):
sources.AsQueryable()
.SelectMany(source => source)
.Where(bar => bar.Xzy == 123)
.Select(bar => bar)
至关重要的是,您的过滤器会先对每个来源进行枚举。
另请注意,AsQueryable()
实际上是多余的,因为它不会使您的来源比现有的更具可查询性,它使您的源的枚举可查询,而且您无论如何都不是在询问那个集合,你是在查询各个来源。
我认为你真正想要的更像是这样:
sources.SelectMany(source => source.Where(bar => bar.Xzy == 123))
这改变了对条款的相对“优先顺序”的解释。
我实际上不确定如何使用LINQ语法制作后者。
更新:实际上,这是一种方式:
from source in sources
let qsource = (from bar in source
where bar.Xzy == 123
select bar)
from result in qsource
select result
由于这个原因,我通常倾向于使用扩展方法来制作非平凡的查询。