EF Core查询:如何按字母排序获取相邻的上/下项数据
问题背景
我有一组按字母顺序排序的数据,加载代码如下:
model.Posters = this.NoTrackSet<Presentation>() .OrderBy(v => v.Title) .AsNoTracking().ToList();
当前UI中用户可点击任意列表项查看对象详情,需要在详情页添加「上一项」「下一项」导航入口,要求在与当前项PresentationTypeId、SessionId一致的记录范围内,按Title字段的字母顺序获取相邻的前、后项数据,不希望通过两次加载全量列表找索引的方式实现,目前编写的未完成代码如下,无法满足需求:
Presentation prevPoster = this.NoTrackSet<Presentation>() .FirstOrDefault(x => x.PresentationTypeId == prs.PresentationTypeId && x.SessionId == prs.SessionId); Presentation nextPoster = this.NoTrackSet<Presentation>() .FirstOrDefault(x => x.PresentationTypeId == prs.PresentationTypeId && x.SessionId == prs.SessionId);
实现方案
直接在数据库查询阶段通过范围过滤+排序取首条的方式实现即可,EF可以将该逻辑翻译为原生SQL执行,不需要加载全量数据,执行效率远高于内存全量遍历:
- 上一项逻辑:筛选同TypeId、同SessionId且Title字母序小于当前项的记录,按Title倒序排列后取第一条,就是离当前项最近的前一条
- 下一项逻辑:筛选同TypeId、同SessionId且Title字母序大于当前项的记录,按Title正序排列后取第一条,就是离当前项最近的后一条
完整实现代码:
// 查询上一项 Presentation prevPoster = this.NoTrackSet<Presentation>() .Where(x => x.PresentationTypeId == prs.PresentationTypeId && x.SessionId == prs.SessionId && x.Title.CompareTo(prs.Title) < 0) .OrderByDescending(v => v.Title) // 存在Title重名场景时,加主键二次排序保证顺序稳定,例:.ThenByDescending(v => v.PresentationId) .FirstOrDefault(); // 查询下一项 Presentation nextPoster = this.NoTrackSet<Presentation>() .Where(x => x.PresentationTypeId == prs.PresentationTypeId && x.SessionId == prs.SessionId && x.Title.CompareTo(prs.Title) > 0) .OrderBy(v => v.Title) // 存在Title重名场景时,加主键二次排序保证顺序稳定,例:.ThenBy(v => v.PresentationId) .FirstOrDefault();
注意:需要保证数据库使用的排序规则和列表页加载时的排序规则一致,就能保证前后项顺序和列表页完全匹配。如果遇到列表首尾项的情况,对应的查询结果会返回null,前端直接隐藏对应的上/下导航按钮即可。
内容的提问来源于stack exchange,提问作者CarComp
相关产品推荐
相关产品推荐

