EF为下面列出的两个类似语句生成不同的sql
var test = dbcontext.Persons.GetAll() .Where(c => c.PersonID == 2) .Select(c => c.PersonName) .FirstOrDefault();`
SELECT [Limit1].[PersonName ] AS [PersonName ] FROM (SELECT TOP (1) [Extent1].[PersonName ] AS [PersonName ] FROM [dbo].[ApplicationRequest] AS [Extent1] WHERE [Extent1].[PersonID ] = @p__linq__0) AS [Limit1]',N'@p__linq__0 uniqueidentifier',@p__linq__0= "2"
我在具有不同Where条件的多个地方使用上述陈述;在一个地方合并逻辑我将条件作为参数传递
Public Void PassPredicate(Func<ApplicationRequest,bool> ReqFunc) { var test = dbcontext.Persons.GetAll() .Where(ReqFunc) .Select(c => c.PersonName) .FirstOrDefault(); }
我把这个函数称为
PassPredicate(c => c.PersonID == 2);
SELECT [Extent1].[PersonID] AS [PersonID],[Extent1].[PersonName ] AS [PersonName ],[Extent1].[DOB] AS [Dob],[Extent1].[Height] AS [Height],[Extent1].[BirthCity] AS [BirthCity],[Extent1].[Country] AS [Country],FROM [dbo].[Person] AS [Extent1]
如果你看第二个sql,它是非常惊人的:它是拉所有信息(列和行).它没有where子句并选择所有列.
从DB返回结果后应用where条件.
第二个语句的唯一区别是我将条件作为参数传递,而不是在where子句中有条件.
谁能解释为什么会有区别?
解决方法
由于ReqFunc类型是Func< ApplicationRequest,bool>您正在使用Enumerable扩展,因此您的代码(Where,Select,FirstOrDefault)将在内存中执行.
要解决此问题,只需将ReqFunc更改为Expression< Func< ApplicationRequest,bool>>使用可查询扩展:
Public Void PassPredicate(Expression<Func<ApplicationRequest,bool>> ReqFunc) { var test = dbcontext.Persons.GetAll().Where(ReqFunc).Select(c => c.PersonName).FirstOrDefault(); }