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

时间:2016-05-20 13:52:43

标签: c# .net entity-framework linq

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子句中包含条件。

任何人都可以解释为什么会有差异吗?

2 个答案:

答案 0 :(得分:6)

由于ReqFunc类型为Func<ApplicationRequest, bool>,您使用Enumerable扩展名,因此您的代码(WhereSelectFirstOrDefault )将在内存中执行。

要解决此问题,只需将ReqFunc更改为Expression<Func<ApplicationRequest, bool>>即可使用Queryable个附加信息:

Public Void PassPredicate(Expression<Func<ApplicationRequest, bool>> ReqFunc)
{
    var test = dbcontext.Persons.GetAll().Where(ReqFunc).Select(c => c.PersonName).FirstOrDefault();
}

答案 1 :(得分:0)

IQueryable Where需要Expression<Func<TSource, bool>>,而不是Func<TSource, bool>,因此调用Where的不同重载,导致查询执行,结果将作为IEnumerable而不是IQueryable返回

public static IQueryable<TSource> Where<TSource>(
this IQueryable<TSource> source,
Expression<Func<TSource, bool>> predicate
)

将您的Func作为表达式传递,您应该得到所需的行为。