Как "впустить" в лямбда-выражение?
Как я могу переписать этот запрос 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 expression не позволяет вычислять среднее значение много раз.
3 ответа
Таким образом, вы можете использовать синтаксис метода расширения, который будет включать на одно лямбда-выражение больше, чем вы используете в настоящее время. Здесь нет let
, вы просто используете многострочную лямбду и объявляете переменную:
var results = Stores.Where(store =>
{
var averagePrice = store.Sales.Average(s => s.Price);
return averagePrice > 250 && averagePrice < 500;
});
Обратите внимание, что я изменил сравнение средней цены, потому что ваши результаты никогда не вернутся (больше 500 и меньше 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);
По сути, вам нужно использовать 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 создает новый анонимный тип для объекта в вашей коллекции, он потребляет много памяти для больших коллекций...
Смотрите здесь для деталей: пусть в цепочках методов расширения
Другой вариант - определить этот метод расширения:
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));
Мы можем избежать накладных расходов на лямбда, используемую во всех других ответах, с помощью встроенного объявления:
public static class FunctionalExtensions
{
public static T Assign<T>(this T o, out T result) =>
result = o;
}
И назовите это так
var results = Stores
.Where(store => store.Sales
.Average(s => s.Price)
.Assign(out var averagePrice) < 500 && averagePrice > 250);