考虑以下代码:
_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
查询(所有在一个表达式中)检索相关消息。这将产生比@Ivan展示的不可避免的解决方法更为合理的SQL。然而,这使代理键不舒服地接近于添加业务含义。 - Gert Arnold