ASP.NET中IQueryable<string>排序失效:Distinct后如何保留OrderBy?
问题:IQueryable去重后排序失效,如何同时保留去重与排序?
尝试对IQueryable<String>进行排序并绑定到SelectList。当前代码能从数据库拉取所有非空的FirstName,但排序不生效,似乎Distinct()函数移除了OrderBy的效果。如何同时保留去重和排序?
前端代码
<select asp-for="FirstName" asp-items="@Model.Firstname_SELECT"> </select>
原后端代码
public SelectList? Firstname_SELECT { get; set; } IQueryable<string> Query = (from m in _context.My_DbSet where !string.IsNullOrEmpty(m.FirstName) orderby m.FirstName select m.FirstName).Distinct(); Firstname_SELECT = new SelectList(await Query.ToListAsync());
尝试的错误代码及报错
报错信息:
string doesn't contain ref of m.FirstName
尝试的代码:
IQueryable<string> Query = (from m in _context.My_DbSet where !string.IsNullOrEmpty(m.FirstName ) orderby m.FirstName select m.FirstName).Distinct().OrderBy(m => m.FirstName);
解决方案
问题根源是EF Core的数据库查询逻辑:先执行OrderBy再Distinct时,数据库的DISTINCT操作会忽略前置排序(因为DISTINCT返回的结果本身是无序的)。正确的处理顺序是先去重,再对去重后的字符串集合排序。
修改后的代码:
public SelectList? Firstname_SELECT { get; set; } IQueryable<string> Query = (from m in _context.My_DbSet where !string.IsNullOrEmpty(m.FirstName) select m.FirstName) .Distinct() .OrderBy(name => name); Firstname_SELECT = new SelectList(await Query.ToListAsync());
也可以用更简洁的方法链写法:
var query = _context.My_DbSet .Where(m => !string.IsNullOrEmpty(m.FirstName)) .Select(m => m.FirstName) .Distinct() .OrderBy(name => name); Firstname_SELECT = new SelectList(await query.ToListAsync());
之前的错误代码之所以报错,是因为Distinct()返回的是IQueryable<string>,此时排序的对象是单个字符串,而非原实体对象,所以不能再引用m.FirstName,直接对当前字符串排序即可。
内容的提问来源于stack exchange,提问作者dave
相关产品推荐
相关产品推荐

