尝试检索子行数时,EF 6的行为正确:只有一个不错的SQL查询。另一方面,EF Core可以按子行计数进行排序,但不会在生成的SQL查询中选择它。它只是迭代每个结果并执行Count(*)
SQL查询。
以下是我的模型类:
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; }
}
以下是查询(用于EF Core和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生成此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生成:
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
和
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=3
和
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=1
和
exec sp_executesql N'SELECT COUNT(*)
FROM [Children] AS [c1]
WHERE @_outer_Id = [c1].[ParentId]',N'@_outer_Id int',@_outer_Id=2
如果我有1000行,它将生成1001个SQL查询。如何解决?
我正在使用最新版本的EF Core(2.0.2)和SQL Server。
答案 0 :(得分:0)
我通过使用连接找到了一种解决方法:
var query = context.Parents
.Join(context.Parents
.Select(p => new
{
Id = p.Id,
ChildrenCount = p.Children.Count(),
}),
l => l.Id,
r => r.Id,
(l, r) => new { l, r.ChildrenCount })
.OrderBy(x => x.l.Name)
.Take(4);
var results = query.ToList();
生成单个查询:
exec sp_executesql N'SELECT TOP(@__p_0) [l].[Id], [l].[Name], [t].[Id], [t].[ChildrenCount]
FROM [Parents] AS [l]
INNER JOIN (
SELECT [p].[Id], (
SELECT COUNT(*)
FROM [Children] AS [c]
WHERE [p].[Id] = [c].[ParentId]
) AS [ChildrenCount]
FROM [Parents] AS [p]
) AS [t] ON [l].[Id] = [t].[Id]
ORDER BY [l].[Name]',N'@__p_0 int',@__p_0=4
它的效率低于ef6,但至少它在一次查询中完成。