【问题标题】:Using an existing IQueryable to create a new dynamic IQueryable使用现有的 IQueryable 创建新的动态 IQueryable
【发布时间】:2011-02-24 21:01:15
【问题描述】:

我有一个查询如下:

var query = from x in context.Employees
    where (x.Salary > 0 && x.DeptId == 5) || x.DeptId == 2
    order by x.Surname
    select x;

以上是原始查询,假设返回 1000 个员工实体。

我现在想使用第一个查询来解构它并重新创建一个如下所示的新查询:

var query = from x in context.Employees
    where ((x.Salary > 0 && x.DeptId == 5) || x.DeptId == 2) && (x,i) i % 10 == 0
    order by x.Surname
    select x.Surname;

此查询将返回 100 个姓氏。

语法可能不正确,但我需要做的是附加一个额外的 where 子句并将 select 修改为单个字段。

我一直在研究ExpressionVisitor,但我不完全确定如何基于现有查询创建新查询。

任何指导将不胜感激。谢谢你。

【问题讨论】:

    标签: entity-framework linq-to-entities expression-trees iqueryable


    【解决方案1】:

    在表达式访问者中,您将覆盖方法调用。检查方法是否为 Queryable.Where,如果是,则方法的第二个参数是 lambda 表达式类型的引用表达式。把它捞出来,你就可以搞砸了。

        static void Main()
        {
            IQueryable<int> queryable = new List<int>(Enumerable.Range(0, 10)).AsQueryable();
            IQueryable<string> queryable2 = queryable
                .Where(integer => integer % 2 == 0)
                .OrderBy(x => x)
                .Select(x => x.ToString());
            var expression = Rewrite(queryable2.Expression);
        }
    
        private static Expression Rewrite(Expression expression)
        {
            var visitor = new AddToWhere();
            return visitor.Visit(expression);
        }
    
        class AddToWhere : ExpressionVisitor
        {
            protected override Expression VisitMethodCall(MethodCallExpression node)
            {
                ParameterExpression parameter;
                LambdaExpression lambdaExpression;
                if (node.Method.DeclaringType != typeof(Queryable) ||
                    node.Method.Name != "Where" ||
                    (lambdaExpression = ((UnaryExpression)node.Arguments[1]).Operand as LambdaExpression).Parameters.Count != 1 ||
                    (parameter = lambdaExpression.Parameters[0]).Type != typeof(int))
                {
                    return base.VisitMethodCall(node);
                }
                return Expression.Call(
                    node.Object,
                    node.Method,
                    this.Visit(node.Arguments[0]),
                    Expression.Quote(
                        Expression.Lambda(
                            lambdaExpression.Type,
                            Expression.AndAlso(
                                lambdaExpression.Body,
                                Expression.Equal(
                                    Expression.Modulo(
                                        parameter,
                                        Expression.Constant(
                                            4
                                        )
                                    ),
                                    Expression.Constant(
                                        0
                                    )
                                )
                            ),
                            lambdaExpression.Parameters
                        )
                    )
                );
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2013-09-16
      • 2011-04-12
      • 2015-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-17
      • 2013-03-08
      相关资源
      最近更新 更多