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

使用ReflectionIT.Mvc.Paging的CreateAsync时触发IAsyncQueryProvider异常

解决ReflectionIT.Mvc.Paging调用CreateAsync时的"IAsyncQueryProvider未实现"异常

问题根源

你遇到的异常本质是:传入PagingList.CreateAsync的IQueryable对象是内存集合转换而来的,它的查询提供器不支持Entity Framework的异步操作。具体原因如下:

  • 你的Repository.ReadAllAsync()方法调用了ToListAsync(),会立刻把所有数据从数据库加载到内存,返回的是IEnumerable<Entity>
  • 后续的Select和AsQueryable()仅对内存中的集合做Linq操作,生成的IQueryable是基于内存的,没有EF Core的异步查询提供器,而PagingList.CreateAsync内部会尝试使用EF异步操作,因此抛出异常。

解决方案

核心思路是让分页逻辑在数据库端执行,而非先加载全量数据到内存再分页。需要修改仓库层和控制器代码:

1. 修改仓库接口与实现,返回IQueryable<TEntity>

IQueryable可以保留查询表达式、延迟执行,直到真正需要数据时才会去数据库查询,这样分页逻辑能下推到数据库,既高效又支持EF异步操作。

仓库接口修改:

public interface IRepository<TEntity>
{
    IQueryable<TEntity> ReadAll(); // 移除async,直接返回IQueryable
}

仓库实现修改:

public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
{
    private readonly DbSet<TEntity> dbSet;

    public Repository(DataContext context) => dbSet = context.Set<TEntity>();

    public IQueryable<TEntity> ReadAll() => dbSet; // 直接返回DbSet(本身就是IQueryable)
}

2. 调整控制器中的查询逻辑

直接操作IQueryable完成ViewModel映射,再传给PagingList.CreateAsync,让分页逻辑在数据库端执行:

public async Task<IActionResult> Index()
{
    // 获取未执行的IQueryable查询,不提前加载数据
    var query = _unitOfWork.RepositoryBase<Entity>().ReadAll()
                .Select(i => new ViewModel() 
                             { 
                                 Id = i.Id, 
                                 Name = i.Name, 
                                 LastName = i.LastName 
                             });

    // 传入支持EF异步的IQueryable,CreateAsync会自动处理分页查询
    var pagingModel = await PagingList.CreateAsync(query, 10, 10, "Name", "Name"); 

    pagingModel.RouteValue = new RouteValueDictionary
    {
        {"row", 10 }
    };

    return View(pagingModel);
}

3. (可选但推荐)优化DbContext注入方式

当前UnitOfWork自行实例化DataContext不符合依赖注入最佳实践,建议改为构造函数注入,并注册DataContext为Scoped生命周期:

在Program.cs中注册DbContext:

builder.Services.AddDbContext<DataContext>(options =>
    options.UseSqlServer("Connection-String"));

修改UnitOfWork:

public class UnitOfWork : IUnitOfWork
{
    private readonly DataContext context;

    // 通过构造函数注入DataContext
    public UnitOfWork(DataContext context) => this.context = context;

    public IRepository<TEntity> RepositoryBase<TEntity>() where TEntity : class
    {    
        return new Repository<TEntity>(context);
    }
}

修改完成后,PagingList.CreateAsync拿到的是EF Core原生的IQueryable,其查询提供器实现了IAsyncQueryProvider,即可正常执行异步分页操作,同时分页逻辑在数据库端执行,性能更优。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 00:45:13