在查询中使用IQueryable.Contains:原IQueryable会多次执行吗?
问题解答
原始ids查询是否会被多次执行?
不会。你定义的ids是IQueryable<T>类型,它只是一个查询表达式,并没有立即触发数据库操作。当你把它用于Where(s => ids.Contains(s.EntityId))时,ORM(比如Entity Framework)会将整个逻辑翻译成单条完整的SQL语句——把ids对应的查询作为子查询嵌入到IN条件中,最终只会向数据库发起一次查询请求。
举个例子,最终生成的SQL大致如下:
SELECT * FROM OtherEntity WHERE EntityId IN (SELECT Id FROM Entities ORDER BY Id)
是否应该在第二次调用前将其加载到内存中?
分两种场景判断:
- 如果ids结果集很小:不需要加载到内存。直接用
IQueryable的方式,生成的子查询在数据库端执行效率足够,还能保留查询的延迟执行特性。 - 如果ids结果集很大:建议加载到内存(比如调用
ToList()或ToArray())。因为数据库对IN子句的参数数量有上限(比如SQL Server默认是2100个),而且大结果集的子查询可能带来性能损耗。加载到内存后,ORM会把Contains转换成带具体参数的IN条件,避免子查询的性能问题。
加载到内存的代码示例:
// 将ids加载到内存集合中 var ids = entities.Select(s => s.Id).OrderBy(s => s).ToList(); // 后续查询使用内存中的ids进行过滤 var filteredEntities = EntityService .For<OtherEntity>() .GetAll() .Where(s => ids.Contains(s.EntityId));
内容的提问来源于stack exchange,提问作者Irmantas Želionis
相关产品推荐
相关产品推荐

