Il ne s’agit pas de la réutilisation d’un résultat, mais plutôt de la déclaration elle-même. Il ne s'agit pas non plus d'une erreur lors de l'utilisation de var, comme indiqué dans: LINQ to SQL: réutiliser l'expression lambda
Par pure curiosité, je me demandais s'il était possible de réutiliser un seul énoncé LINQ.
Disons que j'ai l'instruction LINQ suivante:
.Where(x => x.Contains(""));
Est-il possible d'extraire l'instruction x => x.Contains("")
et d'utiliser une sorte de référence à celle-ci pour une utilisation ultérieure dans, disons, une autre classe?
Donc, je peux l'appeler comme suit: .Where(previouslySavedStatement);
Vous pouvez le stocker dans une variable. Si vous travaillez avec IQueryable
, utilisez:
System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");
Si vous utilisez IEnumerable
, utilisez:
Func<Foo, bool> selector = x => x.Contains("");
Et utilisez-le dans votre requête:
query.Where(selector);
Oui, vous pouvez écrire une fonction contenant la requête que vous souhaitez réutiliser, qui prend et retourne un IQueryable <T>
public IQueryable<T> ContainsEmpty(IQueryable<T> query)
{
return query.Where(x => x.Contains(""));
}
Maintenant, vous pouvez le réutiliser:
query1 = ContainsEmpty(query1);
query2 = ContainsEmpty(another);
Ça dépend. Il existe deux méthodes Where
, Enumerable.Where
et Queryable.Where
. Si vous appliquez le .Where
à une IEnumerable
que la première est appelée, si vous l'appliquez à une IQueryable
, le deuxième est appelé.
Puisque Enumerable.Where
prend dans une Func
, elle n'est pas réutilisable. Puisque Queryable.Where
prend une expression, celle-ci est réutilisable. Vous pouvez le faire comme suit:
var x = new List<string>().AsQueryable();
var query = x.Where (n => n.Contains("some string"));
//Extract the lambda clause
var expr = query.Expression;
var methodExpr = (MethodCallExpression)expr;
var quoteExpr = (UnaryExpression)methodExpr.Arguments[1];
var funcExpr = (Expression<Func<string, bool>>)quoteExpr.Operand;
Vous pouvez ensuite ré-appliquer plus tard l'expression où:
var query2 = x.Where(funcExpr);
J'ai écrit une bibliothèque pour traiter exactement ce problème, elle s'appelle CLink et vous pouvez trouver une implémentation pour EntityFramework ici: https://www.nuget.org/packages/CLinq.EntityFramework
Il permet de créer des extraits de requête et de les utiliser partout dans une requête linq. En suivant l'exemple de Hamid, créez l'expression suivante:
System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");
Vous pouvez maintenant utiliser cette requête partout dans vos requêtes linq comme ceci:
query.AsComposable().Where(o => selector.Pass(o));
En plus de cet exemple simple, vous pouvez également combiner vos extraits de requête:
query.AsComposable().Where(o => selector.Pass(o) || anotherSelector.Pass(o));
ou même les fusionner:
query.AsComposable().Where(o => anotherSelector.Pass(selector.Pass(o)));
Il y a quelques fonctionnalités supplémentaires, mais je pense que c'est vraiment utile, alors jetez-y un coup d'œil :)