GPGVM
GPGVM

Reputation: 5619

Error converting LINQ anonymous type to IList<>

I have the following LINQ join:

var query = _ABC.Table
            .Join(_DEF.Table, cef => ...etc... })
            .Join(_GHI.Table, extf => ...etc...})
            .Select(jcefn=> new { XYZ = jcefn....etc...});

The linq is good and returns what I expect (verified in LINQ pad).

I am the trying to pass the query into an extension method with this signature:

public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
{ ... }

So I thought this would be acceptable:

var FPaged = new PagedList<MyObject>(query.ToList(), pageIndex, pageSize);

But that apparently isn't making the compiler happy. It is saying:

Argument 1: cannot convert from 'System.Collections.Generic.List' to 'System.Linq.IQueryable etc.

So obviously I need to change my linq anonymous type but not sure exactly what to change it to?

Note I did NOT include alot of code for brevity thinking it wasn't needed for understanding but I will gladly edit it in if needed.

Thank You

Upvotes: 3

Views: 1511

Answers (3)

HugoRune
HugoRune

Reputation: 13819

PagedList requires an IQueryable<MyQuery>. Your query object is of type IQueryable<anonymous-type>. To get an IQueryable<MyQuery> you need to change your select to:

var query = _ABC.Table
            .Join(_DEF.Table, cef => ...etc... })
            .Join(_GHI.Table, extf => ...etc...})
            .Select(jcefn=> new MyObject(){ XYZ = jcefn....etc...});

You do not need .ToList() to turn this into an IQueryable, it already is.

However, if you do want to execute and cache the IQueriable before passing it to the function, you could do

var cachedQuery = query.ToList();
var FPaged = new PagedList<MyObject>(cachedQuery.AsQueryAble<MyObject>(), pageIndex, pageSize);

In most cases this is not what you want. The PagedList requires an IQueryable most likely because it will only retrieve the part of the data that is currently needed for a particular page, leaving the rest of the potentially huge dataset behind the query in the database.

But if you actually want to retrieve all the data only once, and then later turn it into a PagedList, this is the way to go. You can then also reuse the cachedQuery in other places, without causing another database retrieval.

Upvotes: 2

Jon Skeet
Jon Skeet

Reputation: 1502376

Well yes - query.ToList() will return a List<T>, which doesn't implement IQueryable<T>. Indeed, the ToList() would render the paging less useful, as it would all be done locally after fetching the whole table into memory.

Just get rid of the call to ToList() and it may well be fine.

EDIT: Okay, if it's not fine because of the anonymous type, adding a ToList call isn't going to help. You either want to use a query which projects to an IQueryable<MyObject>, or if you really want a paged query for the anonymous type, you could add an extension method:

public static class PagingExtensions
{
    public static PagedList<T> Paginate<T>(this IQueryable<T> source,
                                           int pageIndex, int pageSize)
    {
        return new PagedList<T>(source, pageIndex, pageSize);
    }
}

Then you can use:

// TODO: Use a more sensible variable name
var FPaged = query.Paginate(pageIndex, pageSize);

Upvotes: 10

Jaster
Jaster

Reputation: 8579

Get rid of the ToList(). You need an IQueryable not an IList

var FPaged = new PagedList(query, pageIndex, pageSize);

Upvotes: 6

Related Questions