Преобразовать объект типа IQueryable‹› в тип List‹T›?

У меня есть IQueryable<> объект.

Я хочу преобразовать его в List<> с выбранными столбцами, такими как new { ID = s.ID, Name = s.Name }.

Отредактировано

Марк, ты абсолютно прав!

но у меня есть доступ только к методу FindByAll() (из-за моей архитектуры).

И это дает мне весь объект в IQueryable<>

И у меня есть строгое требование (для создания объекта json для тега select) иметь только тип list<> с двумя полями.


person Vikas    schedule 16.04.2009    source источник
comment
Так что же не получится, если вы используете FindByAll(...).Select(s=›new {ID = s.ID, Name = s.Name}).ToList()?   -  person Marc Gravell    schedule 16.04.2009
comment
Обратите также внимание на комментарий под моим ответом о создании собственного типа, если это необходимо. Json.NET может потребовать редактируемые свойства, и в этом случае вам понадобится собственный тип (анонимные типы C# неизменяемы).   -  person Marc Gravell    schedule 16.04.2009


Ответы (5)


Тогда просто Select:

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

(редактировать) На самом деле - в этом случае имена могут быть выведены, поэтому вы можете использовать:

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

что экономит несколько электронов...

person Marc Gravell    schedule 16.04.2009
comment
Согласно моему уровню, я могу получить весь объект только с помощью запроса linq. Это проблема - person Vikas; 16.04.2009
comment
Вы можете объяснить? Я не понимаю комментарий. - person Marc Gravell; 16.04.2009
comment
Если вы имеете в виду, что вам нужно вернуть этот объект между уровнями, вам нужно создать обычный тип с идентификатором и именем и выбрать (s=>new YourType {ID = s.ID, Name = s.Name }) .К списку(); - person Marc Gravell; 16.04.2009
comment
@Brij, какая проблема? это очень неясно; похоже, что основная проблема в вашем коде заключается в том, что ToList() вернет List<T>, а не ArrayList - я подозреваю, что простое использование var data = .... должно быть вашим первым шагом. - person Marc Gravell; 31.10.2017

Добавьте следующее:

using System.Linq

...и позвоните ToList() на IQueryable<>.

person Hannoun Yassir    schedule 16.04.2009
comment
@pauliephonic вы должны начать использовать (каламбур) ReSharper, тогда вам никогда не придется снова вводить оператор using ;-) - person bytedev; 06.02.2013
comment
Просто, точно, красиво! - person Papa Ccompis; 06.01.2018

Конструктор класса List может преобразовать IQueryable для вас:

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

или вы можете просто преобразовать его без метода расширения, конечно:

var list = new List<T>(queryable);
person mmmeff    schedule 23.05.2013
comment
Добро пожаловать. Мне действительно интересно, почему это расширение не было включено в .NET с самого начала... - person mmmeff; 08.07.2013
comment
Извините, я вас не понял. Что вы имеете в виду, почему это расширение не было включено ...? Хотя это работает. - person Khadim Ali; 09.07.2013
comment
Я имею в виду, что IQueryable.ToList() действительно уже должен быть там, глупо, что нам нужно добавить его как расширение самим. - person mmmeff; 09.07.2013

В System.Linq есть ToList() для IQueryable‹> и IEnumerable‹>. Однако это приведет к полному проходу данных, чтобы поместить их в список. Вы теряете свой отложенный вызов, когда делаете это. Ничего страшного, если это потребитель данных.

person Brian Genisio    schedule 16.04.2009

Вот несколько методов расширения, которые я собрал вместе для преобразования IQueryables и IEnumerables из одного типа в другой (например, DTO). Он в основном используется для преобразования из большего типа (т.е. типа строки в базе данных, которая имеет ненужные поля) в меньший.

Положительными сторонами такого подхода являются:

  • для его использования почти не требуется кода — все, что вам нужно, это простой вызов .Transform<DtoType>()
  • он работает так же, как .Select(s=>new{...}), т.е. при использовании с IQueryable он создает оптимальный код SQL, исключая поля Type1, которых нет в DtoType.

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>();
}
person Vedran    schedule 09.09.2011
comment
Для людей, переходящих из миров Hibernate/NHibernate в Linq: функциональность примерно такая же, как у .SetResultTransformer(Transformers.AliasToBean(typeof(DtoType))) от NHibernate или .setResultTransformer(Transformers.aliasToBean) от Hibernate. (DtoType.класс)) - person Vedran; 17.04.2012