我正在编写一些代码,这些代码将LINQ应用于SQL IQueryable<T>,并添加了进一步动态生成的Where子句。例如,这是其中一种方法的框架:

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


我可能将这些方法中的几种链接在一起,并以“跳过/获取”页面结束。

我是否正确地认为,当最终评估IQueryable时,如果lambda表达式中有任何不能翻译为SQL的内容,将引发异常?我特别担心,我可能会意外地执行某些操作,从而导致IQueryable尽早进行评估,然后继续在内存中进行评估(从而获取数千条记录)。

从我读过的一些东西中,我怀疑不会像这样早评估。有人可以确认吗?

最佳答案

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

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

顺便说一句,一种判断方法是否要调用foreach并强制您的lambda进行评估的简单方法是检查该方法的返回值是否为IQueryable。如果返回值是另一个IQueryable,则该方法可能只是添加到表达式中,而不是强制其求值。如果返回值是List<T>,匿名类型或任何看起来像数据而不是IQueryable的值,则该方法必须强制您的表达式求值以获得该数据。

关于c# - LINQ to SQL IQueryable是否可以意外评估?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4915127/

10-13 06:12