c# – 将谓词作为参数传递给Where子句时,EF SQL发生了变化

EF为下面列出的两个类似语句生成不同的sql
var test = dbcontext.Persons.GetAll()
                            .Where(c => c.PersonID == 2)
                            .Select(c => c.PersonName)
                            .FirstOrDefault();`

生成sql

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

生成sql

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

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...