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子句中包含条件。
任何人都可以解释为什么会有差异吗?
答案 0 :(得分:6)
由于ReqFunc
类型为Func<ApplicationRequest, bool>
,您使用Enumerable
扩展名,因此您的代码(Where
,Select
,FirstOrDefault
)将在内存中执行。
要解决此问题,只需将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作为表达式传递,您应该得到所需的行为。