2010-11-27 3 views
1

쿼리에서 테이블 이름을 추출하기 위해 LINQ-SQL 식 트리를 탐색하는 방법이 필요합니다. 쿼리에 사용 된 첫 번째 테이블만으로도 충분할 것입니다.C# 테이블 이름을 추출하는 식 트리 탐색

예 :

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

그리고 이상적인 기능 :

string TableName = ExtractTablesFromQuery(query); 

당신은 그래서 당신이를 위해 "고객은"

답변

4

는 SQL에 LINQ는이 기능을 노출하지 않습니다 문자열을 반환 옵션.

사용 dataContext.GetCommand (MYQUERY) 기능 등을 결합하지만 참여하고자하는 정확한 테이블 이름을 얻을 보장과 함께 제공되는이 조금 까다로운 얻을 수있는 TSQL

을 구문 분석합니다. 표현의 나무가 자신

이 너무 어려운 것이 아니라 SQL의를 추론에 그 LINQ의 문제가 실제로 당신의 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); 
     } 
    } 

당신이 dataContext.GetTables의 결과 (MYQUERY)를 통해 foreach는 것이를 사용하려면;

+0

나는 내 질문에 대답하는 amienG을 영광으로 생각합니다! 아직 테스트하지는 않았지만 여기서 제안한 내용이 정확 해 보입니다. 따라서 답으로 표시 할 것입니다. 고맙습니다!! – msigman

+0

왜 상수를 방문하나요? 그들은 테이블에 있습니까? – HelloWorld