2010-11-27 48 views
1

我需要一種方法來遍歷LINQ-to-SQL表達式樹來提取查詢中的表名。即使只是查詢中使用的第一個表格可能就足夠了。C#遍歷表達式樹來提取表名

例子:

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

和理想的功能:

string TableName = ExtractTablesFromQuery(query); 

將返回字符串 「客戶」

回答

4

LINQ to SQL不給你,讓你有兩個公開此功能選項。

使用dataContext.GetCommand(更改爲MyQuery)函數解析TSQL

這可能會變得有些棘手與連接等,但會保證你得到的是將要涉及的確切的表名。

訪問表達式樹自己

這是不是太困難,但有在LINQ to SQL中推斷的問題,並優化其表的實際使用,所以你不會得到一個100%準確的結果會發生什麼。例如如果你加入了一個表,但沒有返回任何結果,它將會被優化,但是你不會通過訪問表達式樹來知道這一點,除非你像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); 
     } 
    } 

要使用這個,你會比的foreach從dataContext.GetTables結果(更改爲MyQuery);

+0

我很榮幸有||| amienG回覆我的問題!我還沒有測試過,但你在這裏提出的看起來完全正確,所以我打算將其標記爲答案。謝謝!! – msigman 2010-11-29 04:10:42