web-dev-qa-db-fra.com

Convertir un objet de type IQueryable <> en type List <T>?

J'ai un objet IQueryable<>.

Je veux le convertir en List<> Avec des colonnes sélectionnées comme new { ID = s.ID, Name = s.Name }.

Édité

Marc tu as absolument raison!

mais je n'ai accès qu'à la méthode FindByAll() (à cause de mon architecture).

Et cela me donne un objet entier dans IQueryable<>

Et j'ai une exigence stricte (pour créer un objet json pour la balise select) d'avoir seulement le type list<> Avec deux champs.

47
Vikas

Alors juste Select:

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

(modifier) ​​En fait - les noms peuvent être déduits dans ce cas, vous pouvez donc utiliser:

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

ce qui économise quelques électrons ...

64
Marc Gravell

Ajoutez ce qui suit:

using System.Linq

... et appelez ToList() sur le IQueryable<>.

41
Hannoun Yassir

Le constructeur de la classe List peut convertir un IQueryable pour vous:

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

ou vous pouvez simplement le convertir sans la méthode d'extension, bien sûr:

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

System.Linq a ToList () sur IQueryable <> et IEnumerable <>. Cela entraînera cependant un passage complet des données pour les mettre dans une liste. Vous perdez votre invocation différée lorsque vous faites cela. Ce n'est pas grave si c'est le consommateur des données.

6
Brian Genisio

Voici quelques méthodes d'extension que j'ai truquées ensemble pour convertir IQueryables et IEnumerables d'un type à un autre (c'est-à-dire DTO). Il est principalement utilisé pour convertir d'un type plus grand (c'est-à-dire le type de la ligne de la base de données qui contient des champs inutiles) en un plus petit.

Les aspects positifs de cette approche sont:

  • il ne nécessite presque aucun code à utiliser - un simple appel à .Transform<DtoType> () est tout ce dont vous avez besoin
  • il fonctionne exactement comme .Select (s => new {...}) c'est-à-dire que lorsqu'il est utilisé avec IQueryable, il produit le code SQL optimal, à l'exclusion des champs Type1 que DtoType n'a pas.

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>();
}
2
Vedran