[英]Group by column and get first record of group using 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無法翻譯。 要么以可翻譯的形式重寫查詢,要么切換到客戶評估。
在我的情況下,我無法在客戶端進行分組,因為數據太重而無法在只需要最后一行時將所有行下載到客戶端。 在花了一些時間嘗試不同的 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();
此問題與Client vs. Server Evaluation相關。
在執行 GroupBy 之前,需要在_dataContext.SmsMessages
中添加ToList()
操作,將服務端操作轉換為客戶端。
否則,在服務器端, sql 服務器無法識別客戶端方法。
只需將您的代碼更改如下:
var sms = await _dataContext.SmsMessages.ToList()
.GroupBy(message => message.PatientId)
.Select(group => group.OrderByDescending(message => message.CreatedOn).FirstOrDefault())
.ToListAsync();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.