C#Linq提取Where子句

时间:2017-08-30 14:15:18

标签: c# linq where

我有以下Linq查询:

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

4 个答案:

答案 0 :(得分:1)

在答案中关于IEnumerable和IQueryable的答案中有很多混乱,所以我会尽力帮助。首先,IEnumerables使用已编译的代码和带表达式的IQueryable。可以在具有Expression属性的任何IQueryable中访问Expression部分。它将代表您使用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;
            }
        }

但是这是一个简单的例子,它将为您提供第一个它可以找到的地方但是Queriable可以有多个转换等等。我认为使用IEnumerable是不可能的,因为委托引用只存在于您调用的方法的上下文中。

答案 1 :(得分:0)

  

我有以下Linq查询:
  var query1 = qble1.Where(x => x.name == "name" && x.id == 1);
  我正在尝试Where子句提取到变量中,然后我可以在需要时将其重新应用到另一个查询。

这是什么意思?你的意思是,提取提供的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 < / p>

  

我正在尝试实现上面的反转,即编写查询,然后将Where Clause 提取到变量whereClause中,例如
  Expression<Func<testClass, bool>> whereClause = WhereClause of query1

这是什么意思?您是否在给IEnumerable<T> query1这样的问题时,是否可以提取应用于获取IEnumerable<T>的lambda /函数。这甚至有意义吗?

您正在where clause松散地使用LINQExpressionlambda,并且很难理解这意味着什么。你应该改写你的问题,但我试图回答正在提出的文字问题

答案 2 :(得分:-1)

这个where子句是一个lambda表达式。请参阅此answer以实现此目的

答案 3 :(得分:-1)

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

用法:

var refinedSet = filterFunc(originalSet);