简体   繁体   English

使用Func <>而不是lambda时,超时已过期

[英]Timeout expired when using a Func<> instead of a lambda

Given: 鉴于:

public EntityAddress ReadSingle(Func<EntityAddress, bool> predicate)
{
    //var result = Context.CV3Address.FirstOrDefault(a => a.GUID == 1100222);
    var result = Context.CV3Address.FirstOrDefault(predicate);
    return result;
}

FirstOrDefault(a => a.GUID == 1100222); returns a result immediately. 立即返回结果。

FirstOrDefault(predicate); results in a timeout exception. 导致超时异常。 Note that predicate = the lambda expression 注意谓词= lambda表达式

My suspicion is that the latter method attempts to pull down all records which is not gonna happen with a table this large. 我的怀疑是,后一种方法试图拉低所有记录,而这种记录不会在如此大的表中发生。

Why does this happen? 为什么会这样?

It happens because of the type of the predicate, which should have been instead 发生这种情况的原因是谓词的类型,而应改为

Expression<Func<CV3Address, bool>>

If the predicate is an expression tree (as above) and Context.CV3Address is an IQueryable<CV3Address> then EF can translate the expression tree to SQL and directly get the results from the database. 如果谓词是一个表达式树(如上所述),并且Context.CV3AddressIQueryable<CV3Address>则EF可以将表达式树转换为SQL,并直接从数据库中获取结果。

On the other hand, if the predicate is a Func<CV3Address, bool> (a delegate; a pointer to compiled code) then this cannot be translated to SQL. 另一方面,如果谓词是Func<CV3Address, bool> (委托;指向已编译代码的指针),则无法将其转换为SQL。 Therefore LINQ has no other option that to treat your repository as an IEnumerable<CV3Address> , which is a sequence that can be filtered in-memory. 因此,LINQ没有其他选择可将您的存储库视为IEnumerable<CV3Address> ,这是可以在内存中过滤的序列。 That has the side effect of needing to pull all records from the database in order to filter them. 这具有需要从数据库中提取所有记录以对其进行过滤的副作用。

If you hardcode the predicate then the compiler can treat it either as an expression tree or a delegate, and due to the type of Context.CV3Address it treats it as an expression tree. 如果对谓词进行硬编码,则编译器可以将其视为表达式树或委托,并且由于Context.CV3Address的类型,因此会将其视为表达式树。

FirstOrDefault(a => a.GUID == 1100222) creates an expression tree that uses LINQ to Entities to run the query on the DB server. FirstOrDefault(a => a.GUID == 1100222)创建一个表达式树,该树使用LINQ to Entities在数据库服务器上运行查询。

FirstOrDefault(predicate) downloads the entire table and runs the filter locally. FirstOrDefault(predicate)下载整个表并在本地运行过滤器。

You need to change your method to take an expression tree: 您需要更改方法以采用表达式树:

Expression<Func<CV3Address, bool>>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM