Reuse of a LINQ query

一曲冷凌霜 提交于 2019-12-03 06:32:51

问题


This is not about the reuse of a result but more the statement itself. Nor is it about an error when using var as mentioned in: LINQ to SQL: Reuse lambda expression

Out of sheer curiosity I was wondering if it is possible to reuse a single LINQ statement.

Lets say I have the following LINQ statement:

.Where(x => x.Contains(""));

Is it possible to extract the statement x => x.Contains("") and use some kind of reference to this for later usage in, lets say, another class?

So I can call it like: .Where(previouslySavedStatement);


回答1:


You can store it in a variable. If you are working with IQueryable then use:

System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");

If you are using IEnumerable then use:

Func<Foo, bool> selector = x => x.Contains("");

And use it in your query:

query.Where(selector);



回答2:


Yes, you can write a function containing the query you want to reuse, which takes and returns an IQueryable<T>

   public IQueryable<T> ContainsEmpty(IQueryable<T> query)
   {
       return query.Where(x => x.Contains(""));
   }

Now you can reuse it:

   query1 = ContainsEmpty(query1);
   query2 = ContainsEmpty(another);



回答3:


It depends. There's two Where methods, Enumerable.Where and Queryable.Where. If you're applying the .Where to an IEnumerable than the first one is called, if you're applying it to an IQueryable the second one is called.

Since Enumerable.Where takes in a Func, it isn't reusable. Since Queryable.Where takes in an expression, it is reusable. You can do so as follows:

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;

You can then later re-apply the where expression:

var query2 = x.Where(funcExpr);



回答4:


I wrote a library to address exactly this concern, it's called CLink and you can find an implementation for the EntityFramework here: https://www.nuget.org/packages/CLinq.EntityFramework

It allows to create query snippets and use them everywhere you in a linq query. Following the example of Hamid, create the following expression:

System.Linq.Expressions.Expression<Func<Foo, bool>> selector = x => x.Contains("");

You can now use this query everywhere in your linq queries like this:

query.AsComposable().Where(o => selector.Pass(o));

Additionally to this simple example you're also able to combine your query snippets:

query.AsComposable().Where(o => selector.Pass(o) || anotherSelector.Pass(o));

or even merge them together:

query.AsComposable().Where(o => anotherSelector.Pass(selector.Pass(o)));

There's some more features, but I think it's really helpful, so check it out :)



来源:https://stackoverflow.com/questions/34337294/reuse-of-a-linq-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!