Search code examples
asp.net-core

I get the following error when I add paging "IQueryable doesn't implement IAsyncQueryProvider"


I want to implement paging for MVC .NetCore application. I have a list " List<_Item> Items which i got from azure blob" I get the following error when I add paging "IQueryable doesn't implement IAsyncQueryProvider"

Paging I'm trying to Implement: https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/sort-filter-page?view=aspnetcore-3.1

Possible solutions I tried looking at: https://github.com/romantitov/MockQueryable

HomeController: Index function

[Obsolete]
        public async Task<IActionResult> Index(string outletId, string contractId, string sort, string currentFilter, int? pageNumber)
        {
            ViewData["CurrentSort"] = sort;
            ViewData["OutletId"] = String.IsNullOrEmpty(sort) ? "descending outletId" : "";
            ViewData["ContractId"] = sort == "ContractId" ? "descending contractId" : "ContractId";

            if (outletId != null || contractId != null)
            {
                pageNumber = 1;
            }
            else
            {
                outletId = currentFilter;
                contractId = currentFilter;
            }

            blobServices.Add_Tags_on_Blob("GSS_EDM_WorkHistoryTerminationsEngagementsIRP5Request_Dev.csv");
            // List<_Item> Items = (List<_Item>)blobServices.Get_BlobItem_List();

            List<_Item> Items = (List<_Item>)blobServices.Find_Blob_By_Tag(outletId, contractId);
            var records = Items.AsQueryable();

            switch (sort)
            {

                case "descending outletId":
                    records = records.OrderByDescending(x => x.OutletId);
                    break;

                case "descending contractId":
                    records = records.OrderByDescending(x => x.ContractId);
                    break;

                case "ContractId":
                    records = records.OrderBy(x => x.ContractId);
                    break;

                default:
                    records = records.OrderBy(x => x.OutletId);
                    break;

            }

            int pageSize = 3;
            return View(await PaginatedList<_Item>.CreateAsync(records, pageNumber ?? 1, pageSize));
            // return View(Items.ToPagedList(pageNumber ?? 1, 10));
        }

Paging Class[Lines of code with error HomeController

1 Lines of code with error; Pagging Class

public class PaginatedList<T> : List<T>
    {
        public int PageIndex { get; private set; }
        public int TotalPages { get; private set; }

        public PaginatedList(List<T> items, int count, int pageIndex, int pageSize)
        {
            PageIndex = pageIndex;
            TotalPages = (int)Math.Ceiling(count / (double)pageSize);

            this.AddRange(items);
        }

        public bool HasPreviousPage
        {
            get
            {
                return (PageIndex > 1);
            }
        }

        public bool HasNextPage
        {
            get
            {
                return (PageIndex < TotalPages);
            }
        }

        public static async Task<PaginatedList<T>> CreateAsync(IQueryable<T> source, int pageIndex, int pageSize)
        {
            var count = await source.CountAsync();
            var items = await source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToListAsync();
            return new PaginatedList<T>(items, count, pageIndex, pageSize);
        }

Solution

  • According to the error message, we could find The provider for the source IQueryable doesn't implement IAsyncQueryProvider. Only providers that implement IAsyncQueryProvider can be used for Entity Framework asynchronous operations..

    We couldn't let List<T>.AsQueryable() to use ToListAsync method, since it doesn't implement the IAsyncQueryProvider.

    To solve this issue, you could modify the PaginatedList method's CreateAsync method like below:

    public static   PaginatedList<T> Create(IQueryable<T> source, int pageIndex, int pageSize)
    {
        var count =   source.Count();
        var items =  source.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
    
        return new PaginatedList<T>(items, count, pageIndex, pageSize);
    }
    

    Usage:

    return View( PaginatedList<_Item>.Create(records, pageNumber ?? 1, pageSize));