EF Core使用AsSplitQuery后Include中OrderBy排序失效如何解决
问题原因
EF Core 7及更早版本存在已知限制:拆分查询(AsSplitQuery())模式下,Include/ThenInclude链式调用中附加的OrderBy排序、过滤逻辑会被忽略,无法下推到子查询中执行,因此你写的排序规则不会生效。
解决方案
方案1:升级EF Core版本(最推荐)
EF Core 8及以上版本已经修复了该问题,你原有的代码无需修改,保留AsSplitQuery()即可同时解决多集合包含的性能警告、正常生效导航属性的排序规则。
方案2:配置导航属性默认排序(适用于EF Core 6+)
如果暂时无法升级EF Core版本,可以在DbContext的OnModelCreating方法中配置对应导航属性的默认排序规则,不需要在查询的Include中额外编写OrderBy:
protected override void OnModelCreating(ModelBuilder modelBuilder) { // 配置Board的Lists集合默认按Order字段升序 modelBuilder.Entity<Board>() .HasMany(b => b.Lists) .WithOrderBy(l => l.Order); // 配置List的Items集合默认按Order字段升序 modelBuilder.Entity<List>() .HasMany(l => l.Items) .WithOrderBy(i => i.Order); }
配置完成后,查询代码简化为:
public async Task<Board> GetBoardAsync (Guid id) { return await _context.Boards .Include(x => x.Lists) .ThenInclude(x => x.Items) .AsSplitQuery() .FirstOrDefaultAsync(x => x.Id == id); }
方案3:查询后手动内存排序
如果不想修改模型配置,也可以在查询拿到结果后,手动对内存中的导航集合做排序:
public async Task<Board> GetBoardAsync (Guid id) { var board = await _context.Boards .Include(x => x.Lists) .ThenInclude(x => x.Items) .AsSplitQuery() .FirstOrDefaultAsync(x => x.Id == id); if (board != null) { board.Lists = board.Lists.OrderBy(x => x.Order).ToList(); foreach (var list in board.Lists) { list.Items = list.Items.OrderBy(x => x.Order).ToList(); } } return board; }
注意:如果导航集合的数据量极大,该方案会产生额外的内存开销,更推荐使用前两种方案。
内容的提问来源于stack exchange,提问作者Damien
相关产品推荐
相关产品推荐

