1
我需要一種方法來遍歷LINQ-to-SQL表達式樹來提取查詢中的表名。即使只是查詢中使用的第一個表格可能就足夠了。C#遍歷表達式樹來提取表名
例子:
var query = from c in Db.Customers select c;
和理想的功能:
string TableName = ExtractTablesFromQuery(query);
將返回字符串 「客戶」
我需要一種方法來遍歷LINQ-to-SQL表達式樹來提取查詢中的表名。即使只是查詢中使用的第一個表格可能就足夠了。C#遍歷表達式樹來提取表名
例子:
var query = from c in Db.Customers select c;
和理想的功能:
string TableName = ExtractTablesFromQuery(query);
將返回字符串 「客戶」
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);
我很榮幸有||| amienG回覆我的問題!我還沒有測試過,但你在這裏提出的看起來完全正確,所以我打算將其標記爲答案。謝謝!! – msigman 2010-11-29 04:10:42