Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IQueryable to List

Tags:

c#

linq

I'm using System.Linq.Dynamic to allow me to dynamically select a list of fields from a query like this:

finalQuery = query.Select(string.Format("new({0})", string.Join(",", selectors)));

Where selectors is just a List<string> with all the fields I want. This works great, but this version of the extension method Select returns an IQueryable. Not this is not IQueryable<T>. If I have an IQueryable<T> I can simply do a .ToList() to convert it into a list and force the query to actually run on the database, but with the non-generic IQueryable, that method doesn't exists.

This is because ToList is inherited from IEnumerable<T> which IQueryable<T> inherits and IQueryable, obviously, doesn't.

So what's the most efficient way to get an IQueryable to execute the query and give me back a list? I can do this:

List<object> rtn = new List<object>();
foreach (var o in finalQuery)
{
    rtn.Add(o);
}

But it seems like their ought to be an easier way.

Edit: In response to suggestions, I tried both:

finalQuery.Cast<object>().ToList();

and:

finalQuery.Cast<dynamic>().ToList();

Which both give NotSupportedExceptions with the message:

Unable to cast the type 'DynamicClass1' to type 'System.Object'. LINQ to Entities 
only supports casting EDM primitive or enumeration types.
like image 393
Matt Burland Avatar asked Aug 22 '14 18:08

Matt Burland


1 Answers

This appears to be a limitation in the way LINQ to Entities translates IQueryable.Cast with anonymous types. You can work around this by using it as an IEnumerable (your working example does this). This causes the code to do the cast in the .NET runtime after it's retrieved from the DB, instead of trying to handle it in the DB engine. E.g.

IEnumerable finalQuery = query.Select(string.Format("new({0})",
                                                   string.Join(",", selectors)));
var result = finalQuery.Cast<dynamic>().ToList();

Or

public static IList<T> CastToList<T>(this IEnumerable source)
{
    return new List<T>(source.Cast<T>());
}

var finalQuery = query.Select(string.Format("new({0})",
                                            string.Join(",", selectors)));
var result = finalQuery.CastToList<dynamic>();
like image 57
Tim S. Avatar answered Sep 21 '22 17:09

Tim S.