When trying to retrieve the count of child rows, EF 6 behaves correctly: just one nice SQL query. EF Core on the other hand can somewhat order by the count of child rows but does not select it in the generated SQL query. It just iterate through each result and executes a Count(*) SQL query.
Here are my model classes:
public class Parent
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int ParentId { get; set; }
public Parent Parent { get; set; }
}
Here is the the query (used for both EF Core and EF 6):
var query = context.Parents
.Take(4)
.Select(p => new
{
Parent = p,
ChildrenCount = p.Children.Count(),
});
var results = query.OrderBy(x => x.ChildrenCount).ToList();
EF 6 generates this SQL :
SELECT
[Project1].[Id] AS [Id],
[Project1].[Name] AS [Name],
[Project1].[C1] AS [C1]
FROM
(SELECT TOP (4)
[c].[Id] AS [Id],
[c].[Name] AS [Name],
(SELECT COUNT(1) AS [A1]
FROM [dbo].[Children] AS [Extent2]
WHERE [c].[Id] = [Extent2].[ParentId]) AS [C1]
FROM [dbo].[Parents] AS [c]) AS [Project1]
ORDER BY [Project1].[C1] ASC
EF Core generates :
exec sp_executesql N'SELECT [t].[Id], [t].[Name]
FROM (
SELECT TOP(@__p_0) [p].[Id], [p].[Name]
FROM [Parents] AS [p]
) AS [t]
ORDER BY (
SELECT COUNT(*)
FROM [Children] AS [c]
WHERE [t].[Id] = [c].[ParentId]
)',N'@__p_0 int',@__p_0=4
And
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=3
And
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=1
And
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=2
If I had 1000 rows, it would've generated 1001 SQL queries. How to fix that?
I'm using the latest version of EF Core (2.0.2) with SQL Server.