Réutilisation D'une requête LINQ
Il ne s'agit pas de la réutilisation d'un résultat mais plutôt de l'instruction elle-même. Il ne s'agit pas non plus d'une erreur lors de l'utilisation de var comme mentionné dans: LINQ to SQL: Reuse lambda expression
Par pure curiosité, je me demandais s'il était possible de réutiliser une seule instruction 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 à cela pour une utilisation ultérieure dans, disons, un autre de classe?
, Donc je peux l'appeler comme: .Where(previouslySavedStatement);
4 réponses
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
, puis 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 renvoie un IQueryable
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 y a deux méthodes Where
, Enumerable.Where
et Queryable.Where
. Si vous êtes à l'application de la .Where
pour un IEnumerable
que le premier est appelé, si vous l'appliquez à un IQueryable
, le second est appelé.
Depuis Enumerable.Where
une Func
, il n'est pas réutilisable. Puisque Queryable.Where
prend une expression, elle 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 appliquer à nouveau l'expression where:
var query2 = x.Where(funcExpr);
J'ai écrit une bibliothèque pour répondre exactement à cette préoccupation, 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 pour 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 ensemble:
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 vérifiez-le:)