Linq to sql C遍历表达式树以提取表名

Linq to sql C遍历表达式树以提取表名,linq-to-sql,expression-trees,Linq To Sql,Expression Trees,我需要一种方法来遍历LINQ到SQL表达式树,以提取查询中的表名。即使只是查询中使用的第一个表也可能足够了 例如: var query = from c in Db.Customers select c; 理想的功能是: string TableName = ExtractTablesFromQuery(query); 将返回字符串CustomersLINQ to SQL不会为您公开此功能,因此您有两个选项 使用dataContext.GetCommandmyQuery函数并解析TSQL 这

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

例如:

var query = from c in Db.Customers select c;
理想的功能是:

string TableName = ExtractTablesFromQuery(query);

将返回字符串Customers

LINQ to SQL不会为您公开此功能,因此您有两个选项

使用dataContext.GetCommandmyQuery函数并解析TSQL

这在连接等方面可能会有点棘手,但可以保证您得到将要涉及的确切表名

亲自访问表达式树

这并不太困难,但问题在于LINQtoSQL会推断并优化实际使用的表,因此您不会得到100%准确的结果。e、 g.如果您加入了一个表,但没有返回任何结果,那么它将得到优化,但如果您不完全像LINQ to SQL那样进行优化,那么通过访问表达式树就不会知道这一点,这将是一项非常艰巨的工作

如果您想尝试2,下面是一个示例:

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);
        }
    }

要使用它,您需要查看dataContext.GetTablesmyQuery的结果

LINQ to SQL不会为您公开此功能,因此您有两个选择

使用dataContext.GetCommandmyQuery函数并解析TSQL

这在连接等方面可能会有点棘手,但可以保证您得到将要涉及的确切表名

亲自访问表达式树

这并不太困难,但问题在于LINQtoSQL会推断并优化实际使用的表,因此您不会得到100%准确的结果。e、 g.如果您加入了一个表,但没有返回任何结果,那么它将得到优化,但如果您不完全像LINQ to SQL那样进行优化,那么通过访问表达式树就不会知道这一点,这将是一项非常艰巨的工作

如果您想尝试2,下面是一个示例:

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);
        }
    }

要使用它,您需要查看dataContext.GetTablesmyQuery的结果

我很荣幸有阿弥昂回答我的问题!我还没有测试它,但是你在这里提出的建议看起来完全正确,所以我将把它标记为答案。非常感谢。为什么要访问常量?他们曾经坐过桌子吗?我很荣幸有阿弥昂回答我的问题!我还没有测试它,但是你在这里提出的建议看起来完全正确,所以我将把它标记为答案。非常感谢。为什么要访问常量?他们有桌子吗?