假设:
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);
会立即返回结果。
FirstOrDefault(predicate);
会导致超时异常。请注意谓词= lambda表达式
我的怀疑是,后一种方法试图拉下所有记录,这些记录不会发生在这么大的表中。
为什么会这样?
答案 0 :(得分:7)
这是因为谓词的类型,而应该是
Expression<Func<CV3Address, bool>>
如果谓词是表达式树(如上所述)且Context.CV3Address
是IQueryable<CV3Address>
,那么EF可以将表达式树转换为SQL并直接从数据库中获取结果。
另一方面,如果谓词是Func<CV3Address, bool>
(委托;指向已编译代码的指针),则无法将其转换为SQL。因此,LINQ没有其他选项可以将您的存储库视为IEnumerable<CV3Address>
,这是一个可以在内存中过滤的序列。这有副作用,需要从数据库中提取所有记录以过滤它们。
如果您对谓词进行硬编码,那么编译器可以将其视为表达式树或委托,并且由于Context.CV3Address
的类型,它将其视为表达式树。
答案 1 :(得分:3)
FirstOrDefault(a => a.GUID == 1100222)
创建一个表达式树,使用LINQ to Entities在数据库服务器上运行查询。
FirstOrDefault(predicate)
下载整个表并在本地运行过滤器。
您需要更改方法以获取表达式树:
Expression<Func<CV3Address, bool>>