EF Core“Group By 无法翻译,将在本地进行评估。”

cmp*_*des 13 c# ef-core-2.2

我正在使用 Entity Framework Core 2.2.6 对 Sql Server 数据库运行一个简单的查询,但是 GroupBy 没有在服务器上执行,而是在本地执行。

有什么我遗漏的东西会迫使该组进入服务器吗?

我尝试过的 EF 查询的 2 个变体:

public class Holiday
{
    public int Id {get;set;}
    public DateTime Date {get;set;}
    public string Username {get;set;}
    public string Approver {get;set;}
}

//version 1
await _dbContext.Holidays
    .GroupBy(h => new { h.Date})
    .ToDictionaryAsync(x => x.Key.Date, x => x.Select(x1 => x1.Username).ToList());

//version 2
await _dbContext.Holidays
    .GroupBy(h => h.Date)
    .ToDictionaryAsync(x => x.Key, x => x.Select(x1 => x1.Username).ToList());
Run Code Online (Sandbox Code Playgroud)

两种变体都会产生以下 SQL:

SELECT [h].[Id], [h].[Approver], [h].[Date], [h].[HolidayTypeId], [h].[OwningRequestId], [h].[HolidayStatusId], [h].[Username]
FROM [Holidays] AS [h]
ORDER BY [h].[Date]

Run Code Online (Sandbox Code Playgroud)

产生的警告:

警告:Microsoft.EntityFrameworkCore.Query[20500] LINQ 表达式“GroupBy([h].Date, [h])”无法翻译,将在本地进行评估。

来自评论的建议:

//group by string
await _dbContext.Holidays
     .GroupBy(h => h.Username)
     .ToDictionaryAsync(x => x.Key, x => x.Select(x1 => x1.Username).ToList());

//group by part of date
await _dbContext.Holidays
     .GroupBy(h => h.Date.Year)
     .ToDictionaryAsync(x => x.Key, x => x.Select(x1 => x1.Username).ToList());
Run Code Online (Sandbox Code Playgroud)
--group by string
SELECT [h].[Id], [h].[Approver], [h].[Date], [h].[HolidayTypeId], [h].[OwningRequestId], [h].[HolidayStatusId], [h].[Username]
FROM [Holidays] AS [h]
ORDER BY [h].[Username]

--group by part of date
SELECT [h].[Id], [h].[Approver], [h].[Date], [h].[HolidayTypeId], [h].[OwningRequestId], [h].[HolidayStatusId], [h].[Username]
FROM [Holidays] AS [h]
ORDER BY DATEPART(year, [h].[Date])
Run Code Online (Sandbox Code Playgroud)

小智 9

这是因为没有这样的 SQL 查询。

像 SQL 一样思考。如果你想按日期组获取用户名,你需要这两个。

基本上 :

await _dbContext.Holidays
    .GroupBy(h => new { h.Date, h.Username})
    .Select(g => new
        {
          g.Key.Date,
          g.Key.Username
        });
Run Code Online (Sandbox Code Playgroud)

这将产生一个像这样的 SQL 查询。

SELECT [h].[Date],[h].[Username]
FROM [Holidays] AS [h]
GROUP BY [h].[Date],[h].[Username]
Run Code Online (Sandbox Code Playgroud)

之后,您可以根据需要使用数据创建字典的结构。


小智 8

问题是,当您尝试在数据库中分组时,您实际上没有办法在组内实现值。您只能访问非SELECT分组列的分组列或聚合值(通过SUM等)。

例如:

SELECT [h].[Date], [h].[Username]
FROM [Holidays] AS [h]
Run Code Online (Sandbox Code Playgroud)

此查询将生成结果集,其中每一行都有两列,日期和名称。

让我们尝试分组:

SELECT [h].[Date], [h].[Username]
FROM [Holidays] AS [h]
GROUP BY [h.Date]
Run Code Online (Sandbox Code Playgroud)

这个 SQL 查询根本不会被评估,因为从 SQL 服务器的角度来看它是无效的。错误信息是

Column 'Holidays.Username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Run Code Online (Sandbox Code Playgroud)

总结所有这些,您可以按照@Ercan Tirman 的建议进行操作,或者加载所有用户名和日期并将它们分组在内存中:

Column 'Holidays.Username' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Run Code Online (Sandbox Code Playgroud)