c# - 迁移到.net core 3.1后EF OrderBy出现问题

标签 c# entity-framework-core linq-to-entities .net-core-3.1 ef-core-3.1

考虑这段代码:

_dbContext.Messages
    .GroupBy(m => new
        {
            MinId = m.SenderId <= m.RecipientId ? m.SenderId : m.RecipientId,
            MaxId = m.SenderId > m.RecipientId ? m.SenderId : m.RecipientId
        })
        .Select(gm => gm.OrderByDescending(m => m.SentAt).FirstOrDefault());

这样,无论是谁发送的消息,我都会按用户的 ID 对所有对话进行分组。然后,我按组内的 SentAt 日期对消息进行排序,并从每个对话中选择最后一条消息。 问题是这段代码可以工作,而且它把所有的代码都翻译成纯 T-Sql(我使用 SQL Server Profiler 来检查)。但后来我决定将我的项目从 Core 2.1 迁移到 3.1,现在我得到了这个:

The LINQ expression '(GroupByShaperExpression: KeySelector:

new { 
    MinId = (CASE
        WHEN ((m.SenderId) <= (m.RecipientId)) THEN (m.SenderId)
        ELSE (m.RecipientId)
    END), 
    MaxId = (CASE
        WHEN ((m.SenderId) > (m.RecipientId)) THEN (m.SenderId)
        ELSE (m.RecipientId)
    END)
 }, 
ElementSelector:(EntityShaperExpression: 
    EntityType: Message
    ValueBufferExpression: 
        (ProjectionBindingExpression: EmptyProjectionMember)
    IsNullable: False
)
).OrderByDescending(m => m.SentAt)

could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync(). See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

任何解决此问题的想法将不胜感激。

附注我知道我可以深入研究 T-SQL 并为其编写存储过程,但我仍在寻找一种使用 Linq to Entity 实现它的方法。

最佳答案

不幸的是,目前 EF Core 3.0/3.1 仅支持带有键/聚合投影的 GroupBy 服务器转换(类似于 SQL)。

这是 Not Acceptable ,因为尽管 EF6 也没有客户端评估,但它能够成功翻译此类查询。

GroupBy 翻译问题得到解决之前,解决方法是将 GroupBy 替换为 2 个相关子查询 - 第一个仅包含分组键,第二个包含组元素。

在你的情况下,它会是这样的:

var source = _dbContext.Messages
    .Select(m => new
    {
        Key = new
        {
            MinId = m.SenderId <= m.RecipientId ? m.SenderId : m.RecipientId,
            MaxId = m.SenderId > m.RecipientId ? m.SenderId : m.RecipientId
        },
        Message = m
    });

var query = source.Select(e => e.Key).Distinct()
    .SelectMany(key => source
        .Where(e => e.Key.MinId == key.MinId && e.Key.MaxId == key.MaxId)
        .Select(e => e.Message)
        .OrderByDescending(m => m.SentAt)
        .Take(1));

关于c# - 迁移到.net core 3.1后EF OrderBy出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59346353/

相关文章:

c# - MVC 代码查看 Controller 是否仍在使用中

c# - ListView 选择模式无法正常运行

ForEach 中的 c# 静态成员

c# - 使用 Autofac 和 EF Core 3.1 的内存泄漏(从 2.2 迁移后)

c# - 将应用程序作为 Windows 服务运行时程序集文件加载错误

ef-code-first - 在 Entity Framework 7 中添加/插入包含复杂类型的新条目代码优先

linq - 在 Linq 中旋转

c# - 为什么在 C# 中将方法分配给变量?

c# - C# 中的数据绑定(bind)()

entity-framework - Linq 到实体/ Entity Framework 跨 edmx "join"