c# - EF 核心 "Group By could not be translated and will be evaluated locally."

标签 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());

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

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

警告产生:

警告警告: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());
--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])

最佳答案

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

例如:

SELECT [h].[Date], [h].[Username]
FROM [Holidays] AS [h]

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

让我们尝试分组:

SELECT [h].[Date], [h].[Username]
FROM [Holidays] AS [h]
GROUP BY [h.Date]

此 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.

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

var dateAndUsername = await _dbContext.Holidays
    .Select(x => new {x.Date, x.Username})
    .ToArrayAsync();

Dictionary<DateTime, List<string>> grouped = dateAndUsername
    .GroupBy(x => x.Date)
    .ToDictionary(x => x.Key, x => x.Select(y => y.Username).ToList());

关于c# - EF 核心 "Group By could not be translated and will be evaluated locally.",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57807038/

相关文章:

c# - 如何使用证书签署 ActiveX DLL

c# - .NET 中对以 1、10 和 2 开头的字符串进行排序并遵守数字顺序的最短方法是什么?

c# - 脚本资源错误 : This is an invalid script resource request

C# 将 3D 矩阵展平/扩展为锯齿状数组

sql-server - Entity Framework Core + 空间数据正在引发 SRID 无效错误

c# - Xamarin:样式 TabWidget

c# - 如何使用 ValueConversions 检索 Entity Framework Core 的数据库模型

c# - EFCore Postgres 时间戳丢失刻度精度

c# - 如何定义与 ValueObjects 的嵌套模型关系