2013-12-20 71 views
0

我有以下返回根據輸入參數列表(它返回一切,如果沒有有效的輸入被發現)全功能的方法:創建LINQ語句動態組件

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list 

    if ((dekorNr != null) && !dekorNr.Trim().Equals(String.Empty)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Artikelnummer.Contains(dekorNr)); 

    if ((bezeichnung != null) && !bezeichnung.Trim().Equals(String.Empty)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Bezeichnung.Contains(bezeichnung)); 

    if ((hersteller != null) && !hersteller.Trim().Equals(String.Empty)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Lieferant.Contains(hersteller)); 

    return lstFoundPriceRows; 
} 

這三個參數可以是nullString.Empty,應該只用於過濾源列表中,如果它們不是nullString.Empty

正如我所說的代碼工作正常,但我不喜歡它)。這似乎太複雜了。有什麼辦法只創建一個優雅的動態LINQ語句?

+0

好了,你可以替換'((X!= NULL)&&!x.Trim()。等於(的String.Empty))'和'!string.IsNullOrWhitespace(X)'的一個開始。 – Rawling

+0

那麼你可以創建一個方法來構建一個'Func '。但首先要做的就是使用'string.IsNullOrWhiteSpace' –

+0

@ user1567896如果沒有參數爲空,該怎麼辦? –

回答

2

首先,你可以簡化,如果條件:

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list 

    if (!string.IsNullOrWhitespace(dekorNr)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Artikelnummer.Contains(dekorNr)); 

    if (!string.IsNullOrWhitespace(bezeichnung)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Bezeichnung.Contains(bezeichnung)); 

    if (!string.IsNullOrWhitespace(hersteller)) 
     lstFoundPriceRows = lstFoundPriceRows.FindAll(p => p.Lieferant.Contains(hersteller)); 

    return lstFoundPriceRows; 
} 

其次,你可以使用它實際上並不在列表上進行掃描where子句(你是預成型3個掃描現在):

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    IEnumerable<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list 

    if (!string.IsNullOrWhitespace(dekorNr)) 
     lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Artikelnummer.Contains(dekorNr)); 

    if (!string.IsNullOrWhitespace(bezeichnung)) 
     lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Bezeichnung.Contains(bezeichnung)); 

    if (!string.IsNullOrWhitespace(hersteller)) 
     lstFoundPriceRows = lstFoundPriceRows.Where(p => p.Lieferant.Contains(hersteller)); 

    return lstFoundPriceRows.ToList(); 
} 

既然你現在正在做一個掃描反正你可以移動在Where謂詞的條件:

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    IEnumerable<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list 

    lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr)); 

    lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung)); 

    lstFoundPriceRows = lstFoundPriceRows.Where(p => string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller)); 

    return lstFoundPriceRows.ToList(); 
} 

由於您沒有更多的ifs,您可以將這些語句合併爲一個。

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    return _lstABSPriceRows 
      .Where(p => string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr)) 
      .Where(p => string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung)) 
      .Where(p => string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller)) 
      .ToList(); 
} 

最後,我們可以組所有的Where謂詞到一個(感謝@Kris):

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    return _lstABSPriceRows 
      .Where(p => (string.IsNullOrWhitespace(dekorNr) || p.Artikelnummer.Contains(dekorNr)) && 
         (string.IsNullOrWhitespace(bezeichnung) || p.Bezeichnung.Contains(bezeichnung)) && 
         (string.IsNullOrWhitespace(hersteller) || p.Lieferant.Contains(hersteller))) 
      .ToList(); 
} 

您可以通過使用像這樣的擴展方法創建的IsNullOrWhitespace一個簡單(3.5兼容):

public static bool IsNullOrWhitespace(this string s) 
{ 
    return (s == null || string.IsNullOrEmpty(s.Trim())); 
} 

而且它表達變得更簡單:

public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    return _lstABSPriceRows 
      .Where(p => (dekorNr.IsNullOrWhitespace() || p.Artikelnummer.Contains(dekorNr)) && 
         (bezeichnung.IsNullOrWhitespace() || p.Bezeichnung.Contains(bezeichnung)) && 
         (hersteller.IsNullOrWhitespace() || p.Lieferant.Contains(hersteller))) 
      .ToList(); 
} 
+0

在第三個版本中,爲什麼不能有一個'Where'調用?另外,OP應該考慮返回'IEnumerable ',所以你不必在最後使用'.ToList()'。 –

+1

@KrisVandermotten,因爲我一次試圖一步到位,但你先於我。 – Sklivvz

+0

第四,在條件上使用'&&'操作符。 –

0

的代碼運行很好,但太複雜了。例如;如果你輸入一個deKorNr和一個hersteller,會發生什麼?我不知道,如果你能解決這個問題有一個史詩般的LINQ語句,並使它不那麼複雜......

更好的解決方案是創建三個不同的功能,這都有着自己的邏輯。那麼它首先不會要求你的原始問題。

+0

爲什麼要創建三個功能?它會發生,所有三個參數傳遞有效值。如果我有三種方法,我必須連續調用所有三種方法。 – user1567896

+0

如果您的函數從起始帖子被調用,並且所有三個參數都填充了有效值,則會發生以下情況:您的三個函數將執行,但只返回最後一個查詢的結果...因此,您需要添加很多if/elses或修改你的代碼,讓結果集與eachother相交。 –

+0

這正是我想要的:)。我只想要符合所有提供參數的結果。所以如果提供了三個參數,所有參數將用於過濾相同的列表。 – user1567896

0
public List<PriceRow> GetABSPriceRows(string dekorNr, string bezeichnung, string hersteller) 
{ 
    List<PriceRow> lstFoundPriceRows = _lstABSPriceRows; //_lstABSPriceRows is the source list 

    if (!string.IsNullOrWhitespace(dekorNr) || !string.IsNullOrWhitespace(bezeichnung)|| !string.IsNullOrWhitespace(hersteller)) 
     { 
     lstFoundPriceRows = lstFoundPriceRows.Where (p => p.Artikelnummer.Contains(dekorNr) ||   
      p.Bezeichnung.Contains(bezeichnung)||p.Lieferant.Contains(hersteller)).ToList(); 
     }  

    else 
    { 
    // Your query without filters 
    } 
    }