The first method does not load all rows, since the Count method is called from IQueryable , but the second method loads all rows, since it is called from ICollection .
I checked a few checks. I tested it with table 1 and table 2, table 1 of which has PK identifier, and table 2 has FK "Id1" (1: N). I used the EF profiler from here http://efprof.com/ .
First method:
var t1 = context.Table1.Find(1); var count1 = context.Entry(t1) .Collection(t => t.Table2) .Query() .Count();
No Select * From Table2 :
SELECT TOP (2) [Extent1].[Id] AS [Id] FROM [dbo].[Table1] AS [Extent1] WHERE [Extent1].[Id] = 1 SELECT [GroupBy1].[A1] AS [C1] FROM (SELECT COUNT(1) AS [A1] FROM [dbo].[Table2] AS [Extent1] WHERE [Extent1].[Id1] = 1 ) AS [GroupBy1]
Second method:
var t1 = context.Table1.Find(1); var count2 = t1.Table2.Count();
Table 2 is loaded into memory:
SELECT TOP (2) [Extent1].[Id] AS [Id] FROM [dbo].[Table1] AS [Extent1] WHERE [Extent1].[Id] = 1 SELECT [Extent1].[Id] AS [Id], [Extent1].[Id1] AS [Id1] FROM [dbo].[Table2] AS [Extent1] WHERE [Extent1].[Id1] = 1
Why is this happening?
The result of Collection(t => t.Table2) is a class that implements ICollection , but it does not load all the rows and has a property called IsLoaded . The result of the Query method is IQueryable , and this allows you to call Count without first loading the rows.
The result of t1.Table2 is an t1.Table2 , and it loads all the rows to get the score. By the way, even if you use only t1.Table2 , without asking for an account, the rows are loaded into memory.
source share