簡體   English   中英

使用 Linq 按列分組並獲取組的第一條記錄

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM