可以一个LINQ to SQL中的IQueryable被意外地评估?意外地、to、LINQ、IQueryable

2023-09-04 06:25:04 作者:墨夙雅

我写一些code,需要一个LINQ to SQL的的IQueryable< T> 键,进一步增加了动态生成的Where子句。例如这里的方法之一的骨架:

I am writing some code that takes a LINQ to SQL IQueryable<T> and adds further dynamically generated Where clauses. For example here is the skeleton of one of the methods:

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);
}

我可能链几个这样的方法一起用跳过玩完/送页。

I might chain several of these methods together and finish off with a Skip/Take page.

我是正确的思维,当的IQueryable 最后评估,如果有在拉姆达EX pressions无法转换为SQL异常什么将被抛出?特别是我很担心我可能会意外地做一些事情,将导致的IQueryable 早期评估,然后继续评估在内存中(从而拉动千记录)。

Am I correct in thinking that when the IQueryable is finally evaluated if there is anything in the lambda expressions that can't be translated to SQL an exception will be thrown? In particular I'm concerned I might accidentally do something that would cause the IQueryable to evaluate early and then continue the evaluation in memory (thereby pulling in thousands of records).

从一些事情,我读过,我怀疑的IQueryable 不会评估早这样。任何人都可以证实这一点吗?

From some things I've read I suspect IQueryable will not evaluate early like this. Can anyone confirm this please?

推荐答案

是你在想,你的IQueryable可以在运行时抛出一个错误,如果的前pression部分不能转换成SQL正确的。正因为如此,我认为这是一个好主意,有你的查询在业务层类(如数据服务或资料库),并确保该查询有相应的自动测试。

Yes you are correct in thinking that your IQueryable can throw an error at runtime if part of the expression can't be translated into SQL. Because of this I think it's a good idea to have your queries in a Business Layer class (like a data service or repository) and then make sure that query is covered by an automated test.

关于你的Linq EX pression在一个意想不到的时间来评估的基本规则要记住的是,当你调用一个foreach就可以了你的前pression将评估。这也包括调用幕后的foreach像了ToList() FirstOrDefault()的方法。

Regarding your Linq expression evaluating at an unexpected time, the basic rule to keep in mind is that your expression will evaluate whenever you call a foreach on it. This also includes methods that call a foreach behind the scenes like ToList() and FirstOrDefault().

顺便说一句简单的方法来判断一个方法会调用一个foreach,迫使你的lambda评估是检查该方法的返回值是否为一个IQueryable。如果返回值是另一个的IQueryable那么该方法可能只是增加了EX pression但不能强迫它来评估。如果返回值是名单,其中,T&GT; ,匿名类型,或任何看起来像是数据,而不是一个IQueryable,则该方法不得不强迫你的前pression评估以获得这些数据。

BTW an easy way to tell if a method is going to call a foreach and force your lambda to evaluate is to check whether the return value on that method is an IQueryable. If the return value is another IQueryable then the method is probably just adding to the expression but not forcing it to evaluate. If the return value is a List<T>, an anonymous type, or anything that looks like data instead of an IQueryable then the method had to force your expression to evaluate to get that data.