在SelectMany之后找不到ExpressionVisitor的Where表达式

时间:2018-03-26 13:59:05

标签: c# linq linq-expressions

我有一个ExpressionVisitor派生类,其中包含以下重写的VisitMethodCall()方法。

class CommonExpressionVisitor : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        if (node.Method.DeclaringType == typeof(Queryable))
        {
            switch (node.Method.Name)
            {
                case nameof(Queryable.Where):
                    Visit(node.Arguments[0]);
                    return node;

                case nameof(Queryable.Select):
                    Visit(node.Arguments[0]);
                    return node;

                case nameof(Queryable.SelectMany):
                    Visit(node.Arguments[0]);
                    Visit(node.Arguments[1]);
                    Visit(node.Arguments[2]);
                    return node;
            }
        }
        return base.VisitMethodCall(node);
    }
}

当查询中没有Where调用时,访问者可以轻松找到SelectMany表达式。如:

var queryable = from item in collection
                where item.X >= 0 && item.Y >= 0
                select item;

但是,如果查询包含SelectMany,则整个Where表达式消失,访问者无法再访问它。

var queryable = from item in collection
                from sub in item.SubItems
                where sub.A >= 0 && sub.B >= 0
                select sub;

如何修复ExpressionVisitor以查找Where表达式?

1 个答案:

答案 0 :(得分:0)

回答我自己的问题。表达式分为两个阶段。在第一阶段,调用ALTER TABLE your_table WITH CHECK CHECK CONSTRAINT ALL 属性以生成由两个变量IQueryable.Provideritem组成的匿名对象。在第二阶段,再次调用相同的属性,其中表达式现在包含匿名类型和sub子句。因此where子句不会消失,它只是处于第二阶段。