【发布时间】:2019-12-15 17:26:28
【问题描述】:
考虑这段代码:
_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,现在我得到了这个:
LINQ 表达式'(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)
无法翻译。要么重写查询的形式,可以 被翻译,或通过插入显式切换到客户评估 调用 AsEnumerable()、AsAsyncEnumerable()、ToList() 或 ToListAsync()。见https://go.microsoft.com/fwlink/?linkid=2101038 更多信息。
任何解决此问题的想法将不胜感激。
附:我知道我可以深入研究 T-SQL 并为其编写存储过程,但我仍在寻找一种使用 Linq to Entity 实现它的方法。
【问题讨论】:
-
如果你可以相信最近的消息也有最高的
MessageID,你可以得到每个MinId,MaxId对的Max(MessageID),并通过Contains查询检索所属的消息(all in 1表达)。与@Ivan 所展示的其他不可避免的变通方法相比,这产生了更体面的 SQL。然而,这与为代理键添加商业意义相近,令人不安。 -
@GertArnold 谢谢。但问题是 - 我的 MessageId 是 Guid 类型。
-
呵呵,这个解决方案就这么多。
标签: c# entity-framework-core linq-to-entities .net-core-3.1 ef-core-3.1