2013-03-12 54 views
7

我正在使用System.Linq.Expressions.Expression類動態構建SQL「WHERE」子句。它適用於簡單的子句,例如加上「PhaseCode = X」的條款,我做到以下幾點:構建IQueryable.Any用於LINQ查詢的表達式樹

var equalTarget = Expression.Constant(phaseCode, typeof(int?)); 
var phaseEquals = Expression.Equal(Expression.PropertyOrField(projParam, "PhaseCode"), equalTarget); 

不過,現在我想建立如果一個項目已被分配到一個特定的組將返回該記錄的表達式。項目和團隊有多對多的關係。 沒有表達式樹,如下我會做到這一點:

db.Projects.Where(p => .... && p.GroupsAssigned.Any(g => g.ID == groupId)) 

不過,我似乎無法找到一種方式來表達與表達類。 實際上有兩件事情我想不通:

  • 如何遍歷()

  • 之間的關係怎麼辦x.Any任何幫助是極大的讚賞。

  • 回答

    10

    調用擴展方法,如Enumerable.AnyQueryable.Any,僅僅是對序列的靜態方法調用和爲WHERE子句創建的lambda表達式。您可以使用Expression.Call做到這一點:

    // for Enumerable.Any<T>(IEnumerable<T>,Predicate<T>) 
    var overload = typeof(Enumerable).GetMethods("Any") 
               .Single(mi => mi.GetParameters().Count() == 2); 
    var call = Expression.Call(
        overload, 
        Expression.PropertyOrField(projParam, "GroupsAssigned"), 
        anyLambda);  
    

    對於Queryable.Any<T>,你需要推出這一成的方法:

    static Expression BuildAny<TSource>(Expression<Func<TSource, bool>> predicate) 
    { 
        var overload = typeof(Queryable).GetMethods("Any") 
               .Single(mi => mi.GetParameters().Count() == 2); 
        var call = Expression.Call(
         overload, 
         Expression.PropertyOrField(projParam, "GroupsAssigned"), 
         predicate); 
    
        return call; 
    } 
    

    雖然這似乎很奇怪,你是無法通過這樣做一個正常的查詢。

    +0

    感謝解決方案,sixlettervariables。 Expression.Call()正是我所需要的。要回答你的問題,我不能在這種情況下做一個正常的查詢,因爲我不知道在編譯時我的WHERE語句中有多少個AND部分。這完全取決於用戶在搜索表單中所做的選擇。構建表達式樹似乎是唯一有效的解決方案。 – 2013-03-14 13:48:19

    +0

    感謝上帝我看到了這個,我的錯誤是我打電話給 'typeof(Queryable).GetMethods(「Any」)。單(mi => mi.GetParameters()。Count()== 2);' ()); 'typeof(Enumerable).GetMethods(「Any」)。Single(mi => mi.GetParameters()。Count()== 2);' – 2014-12-02 11:54:55