web-dev-qa-db-fra.com

Comment "laisser" l'expression lambda?

Comment puis-je réécrire cette requête linq sur Entity on avec l'expression lambda?
Je veux utiliser le mot clé let ou un équivalent dans mon expression lambda.

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

Pour certaines questions similaires comme ce qui est commenté sous ma question, il est suggéré de

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

qui calculera AveragePrice pour chaque élément, tandis que dans le style de requête que j'ai mentionné, l'expression let empêche de calculer la moyenne plusieurs fois.

39
Reza Owliaei

Ainsi, vous pouvez utiliser la syntaxe de la méthode d'extension, qui impliquerait une expression lambda de plus que celle que vous utilisez actuellement. Il n'y a pas de let, vous utilisez simplement un lambda multiligne et déclarez une variable:

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

Notez que j'ai changé la comparaison du prix moyen, car le vôtre ne retournerait jamais de résultats (plus de 500 ET moins de 250).

L'alternative est

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);
46
Jay

Fondamentalement, vous devez utiliser Select et un type anonyme pour ajouter la moyenne à votre objet, suivi du reste de votre déclaration.

Non testé mais il devrait ressembler à ceci:

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);

Attention, soyez prudent avec ces constructions. L'utilisation de let crée un nouveau type anonyme par objet dans votre collection, elle consomme beaucoup de mémoire avec de grandes collections ...

Regardez ici pour plus de détails: Laissez entrer les méthodes d'extension chaînées

24
Yoeri

Une autre option consiste à définir cette méthode d'extension:

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

Ensuite, écrivez votre requête comme ceci:

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