2010-12-21 34 views
5

我很難找出最好的方法來做到這一點,我會很感激任何幫助。Linq-to-SQL:組合(OR'ing)多個「Contains」過濾器?

基本上,我設置了一個過濾器,允許用戶查看與用戶名的任意「過濾器」相關的審計項目的歷史。數據源是一個SQL Server數據庫,所以我正在使用IQueryable「source」(從db上下文對象獲得的直接表引用,或者可能是由其他查詢產生的IQueryable引用),應用WHERE過濾器,然後返回結果IQueryable對象....但我有點難以理解如何使用這種方法執行OR。

我考慮過去表達式的路由,因爲我知道如何或者那些,但我一直無法弄清楚如何做到這一點與「包含」類型的評估,所以我目前正在使用一個聯盟,但恐怕這可能會對性能產生負面影響,而且我想知道如果其他過濾器(除了此處顯示的用戶名過濾之外)以arbirary順序添加,它是否可能不會給我所需的東西。

這裏是我的示例代碼:

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source) 
{ 
    // Take allowed values... 
    List<string> searchStrings = new List<string>(); 

    // <SNIP> (This just populates my list of search strings) 

    IQueryable<X> oReturn = null; 

    // Step through each iteration, and perform a 'LIKE %value%' query 
    string[] searchArray = searchStrings.ToArray(); 
    for (int i = 0; i < searchArray.Length; i++) 
    { 
     string value = searchArray[i]; 
     if (i == 0) 
      // For first step, perform direct WHERE 
      oReturn = source.Where(x => x.Username.Contains(value)); 
     else 
      // For additional steps, perform UNION on WHERE 
      oReturn = oReturn.Union(source.Where(x => x.Username.Contains(value))); 
    } 
    return oReturn ?? source; 
} 

這感覺就像是錯誤的方式做事情,但它似乎工作,所以我的問題是,第一,是否有更好的方法來做到這一點?另外,有沒有辦法用表達式來做'Contains'或'Like'?

(Editted糾正我的代碼:在回滾到以張貼工作狀態,我顯然沒有回滾相當遠遠不夠:))

========== ===================================

ETA:根據給出的解決方案,這裏是我的新代碼(如果任何閱讀有興趣):

public override IQueryable<X> ApplyFilter<X>(IQueryable<X> source) 
{ 
    List<string> searchStrings = new List<string>(AllowedValues); 

    // <SNIP> build collection of search values 

    string[] searchArray = searchStrings.ToArray(); 

    Expression<Func<X, bool>> expression = PredicateBuilder.False<X>(); 

    for (int i = 0; i < searchArray.Length; i++) 
    { 
     string value = searchArray[i]; 
     expression = expression.Or(x => x.Username.Contains(value)); 
    } 
    return source.Where(expression); 
} 

(一個警告,我注意到:繼PredicateBuilder的例子,一個空的集合Ø f搜索字符串將返回false(false || value1 || ...),而在我原來的版本中,我假設一個空的清單應該只是過濾未過濾的來源。因爲我認爲它更多的,新版本似乎更有意義,我的需要,所以我採取了)

====================== =======================

+0

順便說一句,LINQ確實有[LIKE](http://msdn.microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.like.aspx)方法(不知道你有意使用包含,但你的評論提到LIKE)。 – 2010-12-21 16:20:15

+0

爲什麼不在填充搜索字符串列表的塊中執行where和union操作?換句話說,而不是`searchStrings.Add(newString),`使用`結果= source.Where(X => x.Username.Contains(newString))`或`結果= result.Union(source.Where(X => x.Username.Contains(newString)))`。 – phoog 2010-12-21 17:09:44

回答