IEnumerable与IQueryable的WHERE、TAKE操作执行位置问询
两段代码中WHERE和TAKE的执行位置分析
第一段:IEnumerable场景
IEnumerable<Student> listStudents = DBContext.Students.Where(x => x.Gender == "Male"); listStudents = listStudents.Take(2); foreach (var std in listStudents) { Console.WriteLine(std.FirstName + " " + std.LastName); }
- 尽管
DBContext.Students本身是IQueryable<Student>,但赋值给IEnumerable<Student>变量后,后续调用的Where和Take都是Enumerable类的内存级扩展方法。 - 当
foreach触发枚举时,ORM会先把整张Students表的所有数据加载到本地内存,之后才在内存中依次执行Where过滤男性学生、Take截取前2条的操作。 - 核心结论:WHERE和TAKE都在内存中执行,数据库会返回全表数据。
第二段:IQueryable场景
IQueryable<Student> listStudents = DBContext.Students .AsQueryable() .Where(x => x.Gender == "Male"); listStudents = listStudents.Take(2); foreach (var std in listStudents) { Console.WriteLine(std.FirstName + " " + std.LastName); }
- 变量类型为
IQueryable<Student>,调用的Where和Take都是Queryable类的扩展方法,这些方法不会立即执行逻辑,而是将操作转换成表达式树进行累积。 - 直到
foreach触发枚举时,ORM会把累积的表达式树翻译成对应的SQL语句(例如SELECT TOP 2 * FROM Students WHERE Gender = 'Male'),发送到数据库执行。 - 核心结论:WHERE和TAKE都在数据库端执行,数据库仅返回符合条件的前2条数据,不会加载全表到内存。
内容的提问来源于stack exchange,提问作者rohan
相关产品推荐
相关产品推荐

