Как «впустить» в лямбда-выражение? - PullRequest
39 голосов
/ 11 февраля 2012

Как мне переписать этот запрос linq в Entity с лямбда-выражением?
Я хочу использовать ключевое слово let или эквивалент в моем лямбда-выражении.

var results = from store in Stores
              let AveragePrice =  store.Sales.Average(s => s.Price)
              where AveragePrice < 500 && AveragePrice > 250

Для некоторых подобных вопросов, таких как то, что прокомментировано под моим вопросом, предлагается

.Select(store=> new { AveragePrice = store.Sales.Average(s => s.Price), store})

, которая будет вычислять AveragePrice для каждого элемента, в то время как в упомянутом мною стиле Query выражение let не позволяет вычислять среднее значение много раз.

Ответы [ 3 ]

45 голосов
/ 11 февраля 2012

Таким образом, вы можете использовать синтаксис метода расширения, который будет включать в себя одно лямбда-выражение больше, чем вы используете в настоящее время.let нет, вы просто используете многострочную лямбду и объявляете переменную:

var results = Stores.Where(store => 
{
    var averagePrice = store.Sales.Average(s => s.Price);
    return averagePrice > 250 && averagePrice < 500;
});

Обратите внимание, что я изменил сравнение средней цены, потому что ваши никогда не будут возвращать никаких результатов (более 500 ANDменьше 250).

Альтернатива

var results = Stores.Select(store => new { Store = store, AveragePrice = store.Sales.Average(s => s.Price})
    .Where(x => x.AveragePrice > 250 && x.AveragePrice < 500)
    .Select(x => x.Store);
24 голосов
/ 11 февраля 2012

Как правило, вам нужно использовать Select и анонимный тип, чтобы добавить среднее к вашему объекту, а затем остальную часть вашего утверждения.

Не проверено, но должно выглядеть так:

Stores.Select(
x => new { averagePrice = x.Sales.Average(s => s.Price), store = x})
.Where(y => y.averagePrice > 500 && y.averagePrice < 250)
.Select(x => x.store);

Внимание, будьте осторожны с этими конструкциями.Использование let создает новый анонимный тип для каждого объекта в вашей коллекции, он потребляет много памяти для больших коллекций ...

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

4 голосов
/ 07 августа 2013

Другой вариант - определить этот метод расширения:

public static class Functional
{
    public static TResult Pipe<T, TResult>(this T value, Func<T, TResult> func)
    {
        return func(value);
    }
}    

Затем напишите ваш запрос следующим образом:

var results = Stores
    .Where(store => store.Sales.Average(s => s.Price)
        .Pipe(averagePrice => averagePrice < 500 && averagePrice > 250));
...