EF Core 6中IOrderedEnumerable无ToListAsync定义报错如何解决
首先明确:EF Core 6中的ToListAsync没有被弃用,你遇到的报错是类型不匹配导致的。
问题原因
- 你当前
GetAllOrderByAsync方法的排序参数类型是Func<TEntity, object>,这是LINQ to Objects的委托类型。当你给属于IQueryable类型的DbSet传入Func类型参数时,会触发IQueryable隐式转换为IEnumerable,后续调用OrderBy/OrderByDescending返回的就是内存操作的IOrderedEnumerable类型。 - EF Core的
ToListAsync扩展方法仅针对IQueryable类型提供,IEnumerable类型自然不存在该扩展方法,所以触发报错。 System.Data.Entity是.NET Framework版本的EF 6(非EF Core 6)的命名空间,和EF Core完全不兼容,引入后必然冲突,不需要添加。- 你之前在.NET 5环境可以正常运行,大概率是旧项目中引入了第三方兼容包,给
IEnumerable额外扩展了ToListAsync方法,升级.NET 6后兼容包失效才暴露问题,和EF Core本身的功能无关。
解决方案
最优方案:修改排序参数类型(排序逻辑在数据库侧执行,性能最优)
将方法入参从Func<TEntity, object>修改为Expression<Func<TEntity, object>>,这是表达式树类型,EF Core可以将其翻译为SQL语句,全程操作的都是IQueryable类型,可正常调用ToListAsync。
修改后的代码示例:
public async Task<IEnumerable<TEntity>> GetAllOrderByAsync(Expression<Func<TEntity, object>> orderByExpression, bool sortDesc = false) { _Logger.LogDebug($"Getting all records (async) in Table of type: {typeof(TEntity)} order by {orderByExpression}"); if (_AppUnitOfWork.DBTransactionIsStillRunning()) _Logger.LogDebug("Second transaction started before current transaction completed!"); try { var _result = sortDesc ? await _Table.OrderByDescending(orderByExpression).ToListAsync() : await _Table.OrderBy(orderByExpression).ToListAsync(); return _result; } catch (Exception ex) { _AppUnitOfWork.LogAndSetErrorMessage($"!!!Error Getting all (async) order by: {ex.Message} - Inner Exception {ex.InnerException}"); #if DebugMode throw; #endif } return null; }
如果同步方法GetAllOrderBy也需要排序逻辑在数据库侧执行,也可以同步修改其入参为表达式树类型,避免全表加载到内存后再排序的性能损耗。
应急方案:手动转IQueryable(不推荐,性能差)
如果暂时不想修改入参类型,可以在调用排序方法后手动转换为IQueryable再调用异步方法,该方案会将全表数据加载到内存后再排序,数据量大时性能极差,仅适合临时应急使用:
var _result = sortDesc ? await _Table.OrderByDescending(orderByExpression).AsQueryable().ToListAsync() : await _Table.OrderBy(orderByExpression).AsQueryable().ToListAsync();
补充说明
EF Core 6的所有异步扩展方法都定义在Microsoft.EntityFrameworkCore命名空间下,你现有代码已经引入了该命名空间,不需要额外添加其他EF相关的引用。
内容的提问来源于stack exchange,提问作者wassaza
相关产品推荐
相关产品推荐

