2017-08-30 24 views
0

我有以下LINQ查询:C#的LINQ提取Where子句

var query1 = qble1.Where(x => x.name == "name" && x.id == 1); 

我想给Where子句提取到一个变量,然后我就可以重新申请到另一个查询,当我需要。

为了给你一个稍微不同的视图(希望不要混淆问题的目的),我可以做到以下几点:

Expression<Func<testClass, bool>> whereClause = x => x.name == "name" && x.id == 1;    

var query1 = qble1.Where(whereClause); 

,这将在whereClause变量适用于query1

我我试图实现上述的逆过程,即写出查询,并将Where子句抽取到变量中whereClause例如

Expression<Func<testClass, bool>> whereClause = WhereClause of query1 

可以这样做吗?

我想这样做的原因是为了解决我在这个问题上遇到的问题:

C# Predicate builder with using AND with OR

+0

是的,你可以在静态调用表达式中的第二个参数。如果你知道你想要的重写,你可以通过名字来识别它。 –

+0

换句话说,通过检查生成的IEnumerable ''来检索传递给'Enumerable.Where'的'predicate'参数? –

+0

@ vc74这听起来对我来说 – Alex

回答

1

在答案中出现了很多关于IEnumerable和IQueryable问题的困惑,所以我会尽力帮助解决。首先,IEnumerables使用编译代码和IQueryable使用表达式。 Expression部分可以在任何带表达式属性的IQueryable中访问。它将代表你用Linq表达式树编码。您可以像访问者那样获取Expression的Where部分。

static void Main(string[] args) 
     { 
      var data = new [] 
      { 
       new TestClass{ A = "A" }, 
       new TestClass{ A = "" }, 
       new TestClass{ A = "" }, 
       new TestClass{ A = "" }, 
       new TestClass{ A = "" } 
      }; 

      var queryData = data.AsQueryable(); 

      queryData = queryData. 
       Where(a => a.A == "A").OrderBy(a => a.A); 


      Expression<Func<TestClass, bool>> filter = (new ExpressionGetter<Func<TestClass, bool>>()).GetWhere(queryData); 

      Console.ReadLine(); 
     } 

     public class ExpressionGetter<T> : ExpressionVisitor 
     { 
      private Expression<T> filter; 

      protected override Expression VisitMethodCall(MethodCallExpression node) 
      { 
       if (node.Method.Name == "Where") 
       { 
        var a = node.Arguments[1] as UnaryExpression; 
        filter = (Expression<T>)a.Operand; 

        return node; 
       } 
       else 
       { 
        return base.VisitMethodCall(node); 
       } 
      } 

      public Expression<T> GetWhere<TElement>(IQueryable<TElement> queryData) 
      { 
       filter = null; 

       this.Visit(queryData.Expression); 

       return filter; 
      } 
     } 

不过是一个简单的例子,将让你第一个在那里可以找到但可查询可以有多个何在转换等。我认为IEnumerable是不可能的,因为委托引用只存在于你调用的方法的上下文中。

+0

很好的答案,并解决了实际问题 – Alex

+0

@Alex请记住尽可能多地测试这个概念,我相信我错过了一些可能发生的情况。 –

+0

当然是的 - 我昨天测试了它,似乎都在工作 - 它完全按照我所使用的情况返回lambda表达式。 – Alex

-1

where子句是一个lambda表达式。参阅本answer实现这一

+5

这比提供答案时提供了更好的评论。 – Igor

-1

Func<IQueryable<TestClass>,IQueryable<TestClass> filterFunc = query => query.Where(x => x.name == "name" && x.id == 1);

用法:

var refinedSet = filterFunc(originalSet);

0

我有以下LINQ查询:
var query1 = qble1.Where(x => x.name == "name" && x.id == 1);
我想提取Where条款成为一个变量,其中h我可以在需要时重新应用另一个查询。

这是什么意思?你的意思是,提取提供的lambda x => x.name == "name" && x.id == 1?如果是这样的话,你可以简单地将这个lambda存储在一个变量中。 var a = x => x.name == "name" && x.id == 1

为了给你一个稍微不同的视图(希望不要混淆问题的目的),我可以做到以下几点:
Expression<Func<testClass, bool>> whereClause = x => x.name == "name" && x.id == 1;
var query1 = qble1.Where(whereClause);
,这将在whereClause变量适用于query1

不,这不会编译,如果qble1IEnumerable<T>。您正在传递一个Expression,其中预期有函数或lambda。现在你可以做whereClause.Compile()如果这就是你想要什么,然后再它将应用whereClauseqble1,不计算query1

我想实现的上述倒数,这是编写查询,然后提取Where子句到变量whereClause
Expression<Func<testClass, bool>> whereClause = WhereClause of query1

这是什么意思?您是否要求IEnumerable<T>query1,您可以提取应用于获取该IEnumerable<T>的lambda /函数。这甚至有意义吗?

您正在使用的术语where clause松散的LINQExpressionlambda,这是很难理解这意味着什么。你应该重新回答你的问题,但我试图回答提出的字面问题。