Convert IQueryable<> type object to List<T> type?

C#ListIqueryable

C# Problem Overview


I have IQueryable<> object.

I want to Convert it into List<> with selected columns like new { ID = s.ID, Name = s.Name }.

Edited

Marc you are absolutely right!

but I have only access to FindByAll() Method (because of my architecture).

And it gives me whole object in IQueryable<>

And I have strict requirement( for creating json object for select tag) to have only list<> type with two fields.

C# Solutions


Solution 1 - C#

Then just Select:

var list = source.Select(s=>new { ID = s.ID, Name = s.Name }).ToList();

(edit) Actually - the names could be inferred in this case, so you could use:

var list = source.Select(s=>new { s.ID, s.Name }).ToList();

which saves a few electrons...

Solution 2 - C#

Add the following:

using System.Linq

...and call ToList() on the IQueryable<>.

Solution 3 - C#

The List class's constructor can convert an IQueryable for you:

public static List<TResult> ToList<TResult>(this IQueryable source)
{
    return new List<TResult>(source);
}

or you can just convert it without the extension method, of course:

var list = new List<T>(queryable);

Solution 4 - C#

System.Linq has ToList() on IQueryable<> and IEnumerable<>. It will cause a full pass through the data to put it into a list, though. You loose your deferred invoke when you do this. Not a big deal if it is the consumer of the data.

Solution 5 - C#

Here's a couple of extension methods I've jury-rigged together to convert IQueryables and IEnumerables from one type to another (i.e. DTO). It's mainly used to convert from a larger type (i.e. the type of the row in the database that has unneeded fields) to a smaller one.

The positive sides of this approach are:

  • it requires almost no code to use - a simple call to .Transform<DtoType>() is all you need
  • it works just like .Select(s=>new{...}) i.e. when used with IQueryable it produces the optimal SQL code, excluding Type1 fields that DtoType doesn't have.

LinqHelper.cs:

public static IQueryable<TResult> Transform<TResult>(this IQueryable source)
{
	var resultType = typeof(TResult);
	var resultProperties = resultType.GetProperties().Where(p => p.CanWrite);

	ParameterExpression s = Expression.Parameter(source.ElementType, "s");

	var memberBindings =
		resultProperties.Select(p =>
			Expression.Bind(typeof(TResult).GetMember(p.Name)[0], Expression.Property(s, p.Name))).OfType<MemberBinding>();

	Expression memberInit = Expression.MemberInit(
		Expression.New(typeof(TResult)),
		memberBindings
		);

	var memberInitLambda = Expression.Lambda(memberInit, s);

	var typeArgs = new[]
		{
			source.ElementType, 
			memberInit.Type
		};

	var mc = Expression.Call(typeof(Queryable), "Select", typeArgs, source.Expression, memberInitLambda);
	
	var query = source.Provider.CreateQuery<TResult>(mc);

	return query;
}

public static IEnumerable<TResult> Transform<TResult>(this IEnumerable source)
{
	return source.AsQueryable().Transform<TResult>();
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionVikasView Question on Stackoverflow
Solution 1 - C#Marc GravellView Answer on Stackoverflow
Solution 2 - C#Hannoun YassirView Answer on Stackoverflow
Solution 3 - C#mmmeffView Answer on Stackoverflow
Solution 4 - C#Brian GenisioView Answer on Stackoverflow
Solution 5 - C#VedranView Answer on Stackoverflow