You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何对Queryable调用.Count()后,.ToList()返回0条数据?

问题描述

我现在有一段EF查询代码:

query = query.DistinctBy(q => q.Series.Name)
    .OrderBy(c => c.Series.RoleId.Value == (int)Type.Type1 ? 0 : 1)
    .ThenBy(c => c.Series.RoleId.Value == (int)Type.Type2 ? 0 : 1)
    .ThenBy(s => s.Series.RoleId)
    .AsQueryable();
}

query = query
    .OrderByDescending(a => a.Series.Date)
    .ThenByDescending(a => a.Series.Id);

var total = query.Count();

var states = query
    .Skip((model.pageNumber - 1) * model.pageSize)
    .Take(model.pageSize);
    
var return = Mapper.Map<List<SeriesDTO>>(states);

我的核心需求是获取执行Skip和Take分页操作前的结果集总数,但遇到了奇怪的问题:

  • 直接调用query.Count()返回0,但此时后续的Mapper.Map能正常返回数据
  • 换成query.ToList().Count()能得到正确总数,但此时Mapper.Map返回空数据
  • 我也试过把states直接ToList(),问题依旧
解决方案

问题根源

DistinctBy是LINQ to Objects的方法,并非EF原生支持的查询方法。调用DistinctBy后再转AsQueryable(),实际查询已经在内存中执行了一部分,但后续的OrderByDescending等操作又试图转为数据库查询,导致Count()执行时生成的SQL存在问题,返回0;而ToList()会把所有数据加载到内存,所以能得到正确总数,但此时原query的枚举器已经被耗尽,后续的Skip/Take自然拿不到数据。

修复步骤

  1. 替换DistinctBy为EF支持的去重方式
    如果使用EF Core,可以用GroupBy实现按Series.Name去重,确保整个查询能被EF正确转为SQL执行:
    query = query.GroupBy(q => q.Series.Name)
                 .Select(g => g.First())
                 .OrderBy(c => c.Series.RoleId.Value == (int)Type.Type1 ? 0 : 1)
                 .ThenBy(c => c.Series.RoleId.Value == (int)Type.Type2 ? 0 : 1)
                 .ThenBy(s => s.Series.RoleId)
                 .OrderByDescending(a => a.Series.Date)
                 .ThenByDescending(a => a.Series.Id);
    
  2. 正确获取总数和分页数据
    确保Count()和分页操作基于同一个可被EF正确解析的查询对象:
    // 先获取总数
    var total = query.Count();
    // 再执行分页
    var states = query.Skip((model.pageNumber - 1) * model.pageSize)
                      .Take(model.pageSize)
                      .ToList();
    // 映射DTO
    var result = Mapper.Map<List<SeriesDTO>>(states);
    

临时应急方案(需注意性能)

如果暂时无法替换DistinctBy,可以先把去重后的结果加载到内存,再处理分页和总数:

// 先加载去重排序后的全量数据到内存
var filteredList = query.DistinctBy(q => q.Series.Name)
                       .OrderBy(c => c.Series.RoleId.Value == (int)Type.Type1 ? 0 : 1)
                       .ThenBy(c => c.Series.RoleId.Value == (int)Type.Type2 ? 0 : 1)
                       .ThenBy(s => s.Series.RoleId)
                       .OrderByDescending(a => a.Series.Date)
                       .ThenByDescending(a => a.Series.Id)
                       .ToList();
// 获取总数
var total = filteredList.Count;
// 分页
var states = filteredList.Skip((model.pageNumber - 1) * model.pageSize)
                         .Take(model.pageSize)
                         .ToList();
// 映射DTO
var result = Mapper.Map<List<SeriesDTO>>(states);

注意:这种方式会把所有符合条件的数据加载到内存,数据量大时会影响性能,仅适合小数据量场景。

内容的提问来源于stack exchange,提问作者Chattery

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 09:13:19