Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p><strong>Note:</strong> I wrote this answer when Entity Framework 4 was actual. The point of this answer was not to get into trivial <code>.Any()</code> vs <code>.Count()</code> performance testing. The point was to signal that EF is far from perfect. Newer versions are better... but if you have part of code that's slow and it uses EF, test with direct TSQL and compare performance rather than relying on assumptions (that <code>.Any()</code> is ALWAYS faster than <code>.Count() &gt; 0</code>).</p> <hr> <p>While I agree with most up-voted answer and comments - especially on the point <code>Any</code> signals <em>developer intent</em> better than <code>Count() &gt; 0</code> - I've had situation in which Count is faster by order of magnitude on SQL Server (EntityFramework 4). </p> <p>Here is query with <code>Any</code> that thew timeout exception (on ~200.000 records):</p> <pre><code>con = db.Contacts. Where(a =&gt; a.CompanyId == companyId &amp;&amp; a.ContactStatusId &lt;= (int) Const.ContactStatusEnum.Reactivated &amp;&amp; !a.NewsletterLogs.Any(b =&gt; b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr) ).OrderBy(a =&gt; a.ContactId). Skip(position - 1). Take(1).FirstOrDefault(); </code></pre> <p><code>Count</code> version executed in matter of milliseconds:</p> <pre><code>con = db.Contacts. Where(a =&gt; a.CompanyId == companyId &amp;&amp; a.ContactStatusId &lt;= (int) Const.ContactStatusEnum.Reactivated &amp;&amp; a.NewsletterLogs.Count(b =&gt; b.NewsletterLogTypeId == (int) Const.NewsletterLogTypeEnum.Unsubscr) == 0 ).OrderBy(a =&gt; a.ContactId). Skip(position - 1). Take(1).FirstOrDefault(); </code></pre> <p>I need to find a way to see what exact SQL both LINQs produce - but it's obvious there is a huge performance difference between <code>Count</code> and <code>Any</code> in some cases, and unfortunately it seems you can't just stick with <code>Any</code> in all cases.</p> <p>EDIT: Here are generated SQLs. Beauties as you can see ;)</p> <p><code>ANY</code>:</p> <pre> exec sp_executesql N'SELECT TOP (1) [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created] FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created], row_number() OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number] FROM ( SELECT [Extent1].[ContactId] AS [ContactId], [Extent1].[CompanyId] AS [CompanyId], [Extent1].[ContactName] AS [ContactName], [Extent1].[FullName] AS [FullName], [Extent1].[ContactStatusId] AS [ContactStatusId], [Extent1].[Created] AS [Created] FROM [dbo].[Contact] AS [Extent1] WHERE ([Extent1].[CompanyId] = @p__linq__0) AND ([Extent1].[ContactStatusId] &lt;= 3) AND ( NOT EXISTS (SELECT 1 AS [C1] FROM [dbo].[NewsletterLog] AS [Extent2] WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId]) )) ) AS [Project2] ) AS [Project2] WHERE [Project2].[row_number] > 99 ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4 </pre> <p><code>COUNT</code>:</p> <pre> exec sp_executesql N'SELECT TOP (1) [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created] FROM ( SELECT [Project2].[ContactId] AS [ContactId], [Project2].[CompanyId] AS [CompanyId], [Project2].[ContactName] AS [ContactName], [Project2].[FullName] AS [FullName], [Project2].[ContactStatusId] AS [ContactStatusId], [Project2].[Created] AS [Created], row_number() OVER (ORDER BY [Project2].[ContactId] ASC) AS [row_number] FROM ( SELECT [Project1].[ContactId] AS [ContactId], [Project1].[CompanyId] AS [CompanyId], [Project1].[ContactName] AS [ContactName], [Project1].[FullName] AS [FullName], [Project1].[ContactStatusId] AS [ContactStatusId], [Project1].[Created] AS [Created] FROM ( SELECT [Extent1].[ContactId] AS [ContactId], [Extent1].[CompanyId] AS [CompanyId], [Extent1].[ContactName] AS [ContactName], [Extent1].[FullName] AS [FullName], [Extent1].[ContactStatusId] AS [ContactStatusId], [Extent1].[Created] AS [Created], (SELECT COUNT(1) AS [A1] FROM [dbo].[NewsletterLog] AS [Extent2] WHERE ([Extent1].[ContactId] = [Extent2].[ContactId]) AND (6 = [Extent2].[NewsletterLogTypeId])) AS [C1] FROM [dbo].[Contact] AS [Extent1] ) AS [Project1] WHERE ([Project1].[CompanyId] = @p__linq__0) AND ([Project1].[ContactStatusId] &lt;= 3) AND (0 = [Project1].[C1]) ) AS [Project2] ) AS [Project2] WHERE [Project2].[row_number] > 99 ORDER BY [Project2].[ContactId] ASC',N'@p__linq__0 int',@p__linq__0=4 </pre> <p>Seems that pure Where with EXISTS works much worse than calculating Count and then doing Where with Count == 0.</p> <p>Let me know if you guys see some error in my findings. What can be taken out of all this regardless of Any vs Count discussion is that any more complex LINQ is way better off when rewritten as Stored Procedure ;).</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload