c# - 按列分组并使用 Linq 获取组的第一条记录
问题描述
我正在尝试使用 Linq 查询数据库,以便仅从 SmsMessages 表中获取患者从每个患者发送的最后一条消息。我正在尝试按患者 ID 对消息进行分组,按日期对分组进行排序,然后返回该组的第一条记录,如下所示:
var sms = await _dataContext.SmsMessages
.GroupBy(message => message.PatientId)
.Select(group => group.OrderByDescending(message => message.CreatedOn).FirstOrDefault())
.ToListAsync();
类似问题的几个答案,例如,建议对上述内容进行变体,但在执行查询时收到以下错误:错误:
失败:Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware 1 执行请求时发生未处理的异常。System.InvalidOperationException:LINQ 表达式'(GroupByShaperExpression:KeySelector:(s.PatientId),ElementSelector:(EntityShaperExpression:EntityType:SmsMessage ValueBufferExpression:(ProjectionBindingExpression:EmptyProjectionMember)IsNullable:False)).OrderByDescending(message => message.CreatedOn)'无法翻译。要么以可翻译的形式重写查询,要么切换到客户评估。
解决方案
在我的情况下,我无法在客户端进行分组,因为数据太重而无法在只需要最后一行时将所有行下载到客户端。在花了一些时间尝试不同的 ef core 和 LINQ 表达式之后,我发现的唯一方法是使用使用临时表的 Raw SQL 查询。SQL 查询如下所示:
SELECT message.* FROM message JOIN
(SELECT PatientId, MAX(message.CreatedOn) AS CreatedOn
FROM message GROUP BY message.PatientId) temp
ON (message.PatientId = temp.PatientId and message.CreatedOn = temp.CreatedOn);
然后FromSqlRaw
应该使用该方法使用实体框架调用此查询。
var sms = _dataContext.SmsMessages.FromSqlRaw(
"SELECT message.* FROM message JOIN (SELECT PatientId, MAX(message.CreatedOn) AS CreatedOn FROM message GROUP BY message.PatientId) temp ON (message.PatientId = temp.PatientId and message.CreatedOn = temp.CreatedOn);").
ToList();
推荐阅读
- python - 在尊重日期时间的同时计算滚动分组的乘积
- c++ - 回文字符串问题:为什么我必须放 +1 而不是 -1 才能使这段代码工作?
- java - java - 如何按“/”分割并存储为像java中的树一样分层?
- php - 如何在php中放置php
- php - PHP 变量未填充到表单上的 HTML datetime-local 字段中
- bash - 如何让 Bash 脚本引用本地文件
- xslt - 使用节点和属性上的 group by 从 xml 到 xml 的 xslt 转换
- android - LiveData 和 MVVM 模式
- reactjs - 在 Firestore 和 Firebase Auth 中处理用户数据的最佳方式配置为允许每封电子邮件有多个帐户
- magento - Magento 拒绝执行来自 ' 的脚本
' 因为它的 MIME 类型 ('text/html') 是不可执行的