LINQ表达式无法翻译。以一种可以翻译的形式重写查询

时间:2020-03-26 17:26:36

标签: entity-framework linq

我试图从SQL表中获取每个项目的最后一行。 我正在传递一个用户列表(objectIds列表),并希望获得每个用户的最后一份工作。 这是下面的功能。

   public async Task<List<Job>> GetLastJobs(List<int> objectIds)
    {
        using ManagerContext context = new ManagerContext(_callContext);
        List<Job> jobs = context.Jobs.Where(j => j.ObjectId.HasValue && objectIds.Contains(j.ObjectId.Value)).GroupBy(j => j.ObjectId).Select(j => j.OrderByDescending(p => p.Id).FirstOrDefault()).ToList();
        return null;
    }

在执行时,它返回:

the LINQ expression '(GroupByShaperExpression:
KeySelector: (j.ObjectId),
ElementSelector:(EntityShaperExpression: 
    EntityType: Job
    ValueBufferExpression: 
        (ProjectionBindingExpression: EmptyProjectionMember)
    IsNullable: False
)
)
    .OrderByDescending(p => p.Id)' could not be translated. 

以一种可以翻译的形式重写查询, 或通过插入呼叫明确切换到客户评估 到AsEnumerable(), AsAsyncEnumerable(), ToList(), 或ToListAsync()。 参见https://go.microsoft.com/fwlink/?linkid=2101038 有关更多信息。

我不知道如何,从哪里开始解决问题

1 个答案:

答案 0 :(得分:2)

基本问题是SQL没有像LINQ的GroupBy一样强大的分组运算符。 SQL GROUP BY必须聚合所有非分组列,并且在大多数RDBMS中没有FIRST()聚合函数。因此,您必须使用Windowing Functions编写此查询,而EF Core尚未解决此问题。

编写此查询的另一种方法可以翻译。

  var jobs = db.Jobs.Where(j => j.ObjectId.HasValue && objectIds.Contains(j.ObjectId.Value))
                    .Where(j => j.Id == db.Jobs.Where(j2 => j2.ObjectId == j.ObjectId).Max(j => j.Id))
                    .ToList();

翻译为

SELECT [j].[Id], [j].[ObjectId]
FROM [Jobs] AS [j]
WHERE ([j].[ObjectId] IS NOT NULL AND [j].[ObjectId] IN (1, 2, 3)) AND ([j].[Id] = (
    SELECT MAX([j0].[Id])
    FROM [Jobs] AS [j0]
    WHERE [j0].[ObjectId] = [j].[ObjectId]))