Linq to objects表达式返回一个对象,枚举时会从序列中生成元素。通常,延迟的LINQ-to-Object方法充当管道,因此序列的每个元素在处理下一个元素之前流经处理管道。
a)但是如果Linq-to-Objects查询对Linq-to-Entities查询的结果进行操作,那么当foreach
尝试迭代search
时,每个元素再次流经整个处理处理下一个元素之前的序列(换句话说,是从DB检索的序列中的第一个元素,然后由Enumerable.Where
处理,然后由Enumerable.SelectMany
处理,然后才是从DB中检索的下一个元素)或者是从DB一次检索的整个元素集(当foreach
尝试从序列中读取第一个元素时),然后这些元素才开始流经Linq-to-Objects运算符的处理管道? / p>
var search = context.Contacts.AsEnumerable().
Where(s => s.ContactID > 10).SelectMany(s => s.Address);
谢谢
答案 0 :(得分:1)
EF查询提供程序处理第一个context.Contacts
,它将表达式(从IQueryable
)转换为SQL。
然后,通过AsEnumerable
,与EF查询提供程序的链接被破坏,之后的任何内容都是对象的linq,处理前一语句的结果集。
但是,由于Contact.Address
是一个延迟加载的集合,对于传递管道的每个Contact
,会发出一个新查询来填充它。这是可能的,因为EF使用Contact
的代理类型,它通过EF查询提供程序运行查询的getter覆盖Address
。
正如您可能知道的那样,当您擦除AsEnumerable
时,整个语句将变为Expression
树,EF将转换为一个SQL语句。