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

31
demandé sur Community 2015-12-17 17:42:46

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);
36
répondu Hamid Pourjam 2015-12-17 16:47:34

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);
8
répondu 2015-12-17 15:11:31

Ç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);
5
répondu Shlomo 2015-12-17 14:59:31

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

0
répondu crazy_crank 2018-08-25 17:29:35