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

ASP.NET Core MVC异步分页调用报错原因排查

问题原因及解决方案

这个错误的根源很明确——你提前把EF查询的结果加载到内存中了,然后把内存中的List转成了IQueryable,而这个内存版的IQueryable并没有实现EF异步操作需要的IAsyncQueryProvider。

具体来说:

  • 你的代码里,先通过foreach循环把EF查询的resultsObj(这本来是一个还没执行的EF延迟查询,也就是IQueryable)全部加载到内存的resultList里了。
  • 然后你调用resultList.AsQueryable(),这个时候得到的是Linq to Objects的IQueryable,它的底层查询提供者不是EF的异步查询提供者,所以当PaginatedList.CreateAsync里调用CountAsync、ToListAsync这些异步方法时,就会抛出那个错误。
  • 微软官方指南里的CreateAsync是直接对EF原生的IQueryable操作的,这样EF才能把分页逻辑翻译成SQL在数据库端执行,同时支持异步操作。

修改后的控制器代码

你不需要把查询结果先拉到内存里再转成List,直接在EF的IQueryable上完成投影和分页操作就好:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> GetResultList(ResortDataJoinObj resDeals, int page = 1)
{
    if (ModelState.IsValid)
    {
        // 直接投影成目标类型,不需要提前加载到内存
        var resultsQuery = from rd in _db.ResortData
                           join ra in _db.ResortAvailability on rd.RecNo equals ra.RecNoDate
                           where ra.TotalPrice < Int32.Parse(resDeals.priceHighEnd) 
                              && ra.TotalPrice > Int32.Parse(resDeals.priceLowEnd)
                           select new ResortDealResultsObject
                           {
                               Name = rd.Name,
                               ImageUrl = rd.ImageUrl,
                               ResortDetails = rd.ResortDetails,
                               CheckIn = ra.CheckIn,
                               Address = rd.Address,
                               TotalPrice = ra.TotalPrice
                           };

        int pageSize = 3;
        // 直接传入EF的IQueryable,而不是内存List转的IQueryable
        var model = await PaginatedList<ResortDealResultsObject>.CreateAsync(resultsQuery, page, pageSize);
        
        ResortDataJoinObj joinObj = new ResortDataJoinObj();
        joinObj.PageList = model;
        ViewBag.rowsReturned = true;
        return View(joinObj);
    }
    return View(resDeals);
}

关键修改点

  1. 去掉内存加载步骤:直接将EF查询投影为ResortDealResultsObject类型,避免用foreach把所有数据拉到内存。
  2. 传递原生EF查询:把resultsQuery(EF原生的IQueryable)直接传给PaginatedList.CreateAsync,这样EF会处理异步操作,同时把分页逻辑翻译成SQL在数据库端执行,性能比加载全部数据到内存再分页要好得多。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:02:17