如何使用Entity Framework获取每个父项的最新条目列表?
解决方法
方法1:分组子查询关联
先筛选未删除的数据,按ParentId分组找出每个分组的最新LastUpdate时间,再通过ParentId和LastUpdate关联原表,拿到完整的最新行数据:
var latestUpdates = _context.Children .Where(x => !x.Deleted) .GroupBy(x => x.ParentId) .Select(g => new { ParentId = g.Key, MaxLastUpdate = g.Max(x => x.LastUpdate) }); var latestList = _context.Children .Where(x => !x.Deleted) .Join(latestUpdates, child => new { child.ParentId, child.LastUpdate }, update => new { update.ParentId, update.MaxLastUpdate }, (child, update) => child) .ToList();
方法2:使用窗口函数(推荐)
利用SQL的ROW_NUMBER()窗口函数,按ParentId分区、LastUpdate降序排序后给每行标记序号,筛选序号为1的行就是每个ParentId对应的最新记录。EF Core 3.0+支持直接将这种逻辑转换为SQL:
var latestList = _context.Children .Where(x => !x.Deleted) .Select(x => new { Child = x, RowNumber = EF.Functions.RowNumber() .Over( partitionBy: x.ParentId, orderBy: x.LastUpdate descending ) }) .Where(x => x.RowNumber == 1) .Select(x => x.Child) .ToList();
原代码失效原因
DistinctBy是LINQ to Objects的内存操作方法,EF Core无法将其转换为对应的SQL语句,会尝试先把所有符合!x.Deleted条件的数据加载到本地内存再处理,不仅效率低下,还会抛出无法转换的异常。
内容的提问来源于stack exchange,提问作者Robin Khan
相关产品推荐
相关产品推荐

