Могу ли я применить преобразование к каждому элементу в IQueryable и получить результат как IQueryable? - PullRequest
0 голосов
/ 04 января 2019

В моем приложении на C # у меня есть метод, который возвращает IQueryable, где MyClass является классом для кода Entity Framework в первую очередь. Похоже на это.

// Is a class for Entity Framework code-first
public class MyClass
{
    public int Id {get; set;}
    public int LuckyNumber {get; set;}
}

public IQueryable<MyClass> GetQuery()
{
    var query = doSomethingToGetQuery();
    return query;
}

Предположим, я хочу создать метод, который возвращает IQueryable, но я хочу, чтобы мой запрос применил какое-то преобразование к данным перед его возвратом.

Если бы у меня был метод, который возвращал IEnumerable, я мог бы написать что-то вроде этого:

public IEnumerable<MyClass> GetEnumerable()
{
    var query = doSomethingToGetQuery();
    return query.Select(x =>
    {
        var y = x;
        y.LuckyNumber = 2 * x.LuckyNumber;
        return y;
    }
}

Таким образом, у меня был бы IEnumerable, который бы возвращал те же данные, что и исходная функция, но это удвоило бы LuckyNumber.

Предположим, я хочу сделать что-то подобное, но я хочу вернуть IQueryable, где результат будет таким же, как запрос исходного запроса, но в результате значение LuckyNumber удваивается или применяется какое-то другое преобразование.

Кроме того, я не хочу выполнять SQL-запрос, который возвращает весь набор данных, особенно если я получаю одну запись по идентификатору.

Могу ли я сделать это в C #?

1 Ответ

0 голосов
/ 04 января 2019

Предположим, я хочу создать метод, который возвращает IQueryable, но я хочу, чтобы мой запрос применил некоторое преобразование к данным перед его возвратом.

Конечно. Вам просто нужно позвонить Queryable.Select вместо Enumerable.Select . Если вы передадите Func<TSource,TResult>, то он преобразуется в вызов Enumerable.Select, и ваш запрос будет выполнен до применения дополнительных выражений.

Однако, если вы передадите Expression<Func<TSource,TResult>>, то перегрузка разрешится в Queryable.Select, и ваш запрос будет изменен, с новой проекцией, обертывающей существующий запрос.

Самый простой способ получить это право - это LINQ. EG:

public IQueryable<MyClass> GetEnumerable()
{
    IQueryable<MyClass> query = null; //whatever

    IQueryable<MyClass> q2 = 
             from m in query
             select new MyClass()
             {
                 LuckNumber = m.LuckNumber * 2
             };
    return q2;      
 }

Обратите внимание, что если вы сделаете это, вы, вероятно, потеряете способность ORM написать эффективный запрос, который проталкивает предикаты через проекцию на базовые таблицы.

...