简体   繁体   English

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

[英]Why is the generated query from LinQ different if I build the where-clause dynamically for a COUNT()?

I want to count rows for a certain query for which I build the WHERE -clause dynamically. 我想为我动态建立WHERE -clause的特定查询计算行数。

What excited me was the difference I saw when building this in two different ways. 令我兴奋的是,以两种不同的方式构建它时看到的差异。

Try 1 尝试1

int resultsCount = context.MyView.Where(x => x.Id > 100000).Count();

in the profiler I see, that the following query is being executed: 在分析器中,我看到正在执行以下查询:

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]

Try 2 试试2

But I have to check for multiple conditions and not all of them need to be met for every execution. 但是我必须检查多个条件,并非每次执行都需要满足所有条件。 So I tried building the WHERE -clause for my COUNT dynamically (referring to this post ): 所以我尝试为我的COUNT动态构建WHERE- WHERE (请参阅此文章 ):

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

I would expect to see the same or at least a similar query being executed, but instead I see the following in the profiler: 我希望看到正在执行相同或至少一个类似的查询,但相反,我在探查器中看到以下内容:

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]

The value of resultsCount however is the same, but why are those queries so different and where does LinQ get the COUNT for the second query, because I do not see any COUNT being selected? 但是resultsCount的值是相同的,但是为什么这些查询如此不同?LinQ在哪里获得第二个查询的COUNT ,因为我看不到选择了任何COUNT

Can someone tell me how I can force a query similar to the first but still build my WHERE -clause dynamically? 有人可以告诉我如何强制执行与第一个查询类似的查询,但仍然可以动态构建我的WHERE- WHERE吗?

Any hints would be much appreciated. 任何提示将不胜感激。

You're calling Compile on your expression. 您正在对表达式调用Compile

This transforms it from an Expression<Func<MyView, bool>> into a Func<MyView, bool> . 这会将其从Expression<Func<MyView, bool>>转换为Func<MyView, bool> Since it's just a delegate, and not an Expression , it no longer matches the signature for the IQueryable overload of Where , it only matches the IEnumerable overload. 由于它只是一个委托,而不是一个Expression ,它不再与WhereIQueryable重载的签名匹配,它仅与IEnumerable重载匹配。

This means that the query isn't translated into SQL; 这意味着该查询不会转换为SQL。 you are querying the data with no filtering at all, and then doing the filtering in LINQ to objects on the client side. 您要查询的数据完全没有过滤,然后在LINQ中对客户端上的对象进行过滤。

It's important that you not compile the lambda if you want the query to be translated into SQL by the query provider. 如果希望查询提供程序将查询转换为SQL,请不要编译lambda,这一点很重要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM