可以意外地评估LINQ to SQL IQueryable吗?

我正在编写一些代码,它采用LINQ to SQL IQueryable并进一步添加动态生成的Where子句。 例如,这里是其中一个方法的骨架:

 IQueryable ApplyContains(IQueryable source, string field, string value) { Expression<Func> lambda; ... dynamically generate lambda for p => p..Contains(value) ... return source.Where(lambda); } 

我可以将这些方法中的几个链接在一起,并使用Skip / Take页面完成。

我是否正确地认为,当最终评估IQueryable时,如果lambda表达式中有任何内容无法转换为SQL,则会抛出exception? 特别是我担心我可能会意外地做一些会导致IQueryable提前评估然后继续在内存中进行评估的事情(从而吸引成千上万的记录)。

从我读过的一些事情我怀疑IQueryable不会像这样早期评估。 有谁能确认一下吗?

是的,您认为如果表达式的一部分无法转换为SQL,您的IQueryable可能会在运行时抛出错误,这是正确的。 因此,我认为将您的查询放在Business Layer类(如数据服务或存储库)中是个好主意,然后确保查询被自动化测试覆盖。

关于您在意外时间进行评估的Linq表达式,要记住的基本规则是,只要您在其上调用foreach,您的表达式就会进行评估。 这还包括在ToList()FirstOrDefault()类的幕后调用foreach的方法。

BTW是一种简单的方法来判断方法是否要调用foreach并强制lambda进行求值是检查该方法的返回值是否为IQueryable。 如果返回值是另一个IQueryable,那么该方法可能只是添加到表达式但不强制它进行求值。 如果返回值是List ,匿名类型或看起来像数据而不是IQueryable的任何内容,则该方法必须强制您的表达式进行求值以获取该数据。

你的想法是正确的。

只要您在Where子句中传递IQueryable一个Expression ,它就不会意外地进行评估。

此外,以“To”开头的扩展方法将导致评估(即ToList(),ToArray())。