如果我为COUNT()动态构建where子句,为什么LinQ生成的查询会有所不同?

时间:2013-09-30 13:50:20

标签: c# sql sql-server linq count

我想计算某个查询的行,我为此动态构建了WHERE - 子句。

让我感到兴奋的是我在以两种不同的方式构建它时所看到的差异。

尝试1

int resultsCount = context.MyView.Where(x => x.Id > 100000).Count();
在我看到的分析器中

,正在执行以下查询:

SELECT 
[GroupBy1].[A1] AS [C1]
FROM ( SELECT 
    COUNT(1) AS [A1]
    FROM (SELECT 
      [MyView].[Id] AS [Id], 
      [MyView].[EventTypeId] AS [EventTypeId], 
      [MyView].[EventSourceId] AS [EventSourceId], 
      [MyView].[TraceLevelId] AS [TraceLevelId], 
      [MyView].[TimeCreated] AS [TimeCreated], 
      [MyView].[Data1MaxStr] AS [Data1MaxStr]
      FROM [dbo].[MyView] AS [MyView]) AS [Extent1]
    WHERE [Extent1].[Id] > 100000
)  AS [GroupBy1]

尝试2

但我必须检查多个条件,并不是每次执行都需要满足所有条件。所以我尝试动态地为我的WHERE构建COUNT - 子句(引用此post):

var parameter = Expression.Parameter(typeof(MyView), "x");
Expression<Func<MyView, bool>> check1 = x => x.Id > 100000;
Expression expression = Expression.Constant(true);
expression = Expression.AndAlso(expression, Expression.Invoke(check1, parameter));
var lambda = Expression.Lambda<Func<MyView, bool>>(expression, parameter);

int resultsCount = context.MyView.Where(lambda.Compile()).Count();

我希望看到执行相同或至少类似的查询,但我在分析器中看到以下内容:

SELECT 
[Extent1].[Id] AS [Id], 
[Extent1].[EventTypeId] AS [EventTypeId], 
[Extent1].[EventSourceId] AS [EventSourceId], 
[Extent1].[TraceLevelId] AS [TraceLevelId], 
[Extent1].[TimeCreated] AS [TimeCreated], 
[Extent1].[Data1MaxStr] AS [Data1MaxStr]
FROM (SELECT 
      [MyView].[Id] AS [Id], 
      [MyView].[EventTypeId] AS [EventTypeId], 
      [MyView].[EventSourceId] AS [EventSourceId], 
      [MyView].[TraceLevelId] AS [TraceLevelId], 
      [MyView].[TimeCreated] AS [TimeCreated], 
      [MyView].[Data1MaxStr] AS [Data1MaxStr]
      FROM [dbo].[MyView] AS [MyView]) AS [Extent1]

但是resultsCount的值是相同的,但为什么这些查询如此不同,LinQ在哪里获得第二个查询的COUNT,因为我没有看到任何COUNT被选中了?

有人可以告诉我如何强制执行与第一个类似的查询但仍然动态构建我的WHERE - 子句吗?

任何提示都会非常感激。

1 个答案:

答案 0 :(得分:1)

您在表达式上调用了Compile

这会将其从Expression<Func<MyView, bool>>转换为Func<MyView, bool>。由于它只是一个代理,而不是Expression,因此它不再匹配IQueryable Where重载的签名,它只匹配IEnumerable重载。

这意味着查询未转换为SQL;你是在没有过滤的情况下查询数据,然后在LINQ中对客户端的对象进行过滤。

如果您希望查询提供程序将查询转换为SQL,那么编译lambda非常重要。