代码之家  ›  专栏  ›  技术社区  ›  msigman

C遍历表达式树以提取表名

  •  1
  • msigman  · 技术社区  · 15 年前

    我需要一种方法来遍历LINQ to SQL表达式树,以提取查询中的表名。即使只是查询中使用的第一个表也可能足够。

    例子:

    var query = from c in Db.Customers select c;
    

    理想功能:

    string TableName = ExtractTablesFromQuery(query);
    

    将返回字符串“客户”

    1 回复  |  直到 14 年前
        1
  •  4
  •   DamienG    15 年前

    public static class TableFinder
    {
        public static IEnumerable<string> GetTableNames(this DataContext context, IQueryable queryable) {
            var visitor = new TableFindingVisitor(context.Mapping);
            visitor.Visit(queryable.Expression);
            return visitor.Tables.Select(t => t.TableName).Distinct().AsEnumerable();
        }
    
        class TableFindingVisitor : ExpressionVisitor
        {
            private readonly HashSet<MetaTable> foundTables = new HashSet<MetaTable>();
            private readonly MetaModel mapping;
    
            public TableFindingVisitor(MetaModel mapping) {
                this.mapping = mapping;
            }
    
            public override Expression Visit(Expression node) {
                return base.Visit(node);
            }
    
            protected override Expression VisitConstant(ConstantExpression node) {
                if (node.Type.GetGenericTypeDefinition() == typeof(Table<>))
                    CheckType(node.Type.GetGenericArguments()[0]);
                return base.VisitConstant(node);
            }
    
            protected override Expression VisitMember(MemberExpression node) {
                CheckType(node.Member.DeclaringType);
                return base.VisitMember(node);
            }
    
            public IEnumerable<MetaTable> Tables { get { return foundTables; } }
    
            private void CheckType(Type t) {
                var table = mapping.GetTable(t);
                if (table != null && !foundTables.Contains(table))
                    foundTables.Add(table);
            }
        }