2012-09-26 25 views
0

我希望有3-4個搜索選項。現在我在If語句中使用我的查詢。用於過濾的多個選項linq

 if inputcol1 > 0 And Not inputCol2 = "" then 
     Dim list = (From P In db.table 
        Where P.column1 = inputCol1 and P.column2 = inputCol2 
        Select P).ToList() 
    end if 

和一個(或4)更多與另一個條件,但幾乎相同的查詢,只是一個不同的where子句。所以這個查詢是簡化和簡短的。所以如果我有一個非常大的查詢,這將是一個大混亂。而且我不希望其他程序員只爲幾個選項讀取太多的代碼。

是否有一個恰當的簡單方法來查看是否填充並查詢了搜索選項?

+0

如果返回類型與上述查詢相同,則使用傳遞的參數創建分離函數...請隨時調用它... –

回答

0

最好的辦法是有條件地擴大你的查詢:與

Dim query = (From P In db.table Select P) 

If inputCol1.HasValue 
    query = (From P in query Where P.column1 = inputCol1 Select P) 
End If 
If inputCol2.HasValue 
    query = (From P in query Where P.inputCol2 = inputCol2 Select P) 
End If 
' And so on... 

Dim list = query.ToList() 

條件過濾Not inputCol2.HasValue OrElse P.Value = inputCol2將創建一個含有無用謂詞的查詢。通過有條件地擴展你的查詢,只有重要的謂詞纔會被合併。

+0

你是什麼意思無用的謂詞?據我所見,您的解決方案將爲每個參數創建一個額外的查詢,這會導致更詳細的代碼。在這個語句中,如果'Or'運算符的第一部分爲true,那麼編譯器將忽略過濾器'not inputCol2.HasValue orElse P.Value = inputCol2'。 –

+0

@WilsonJimenez看一下SQL。你會看到無用的謂詞。如果你不想過濾變量1,它應該不會顯示在查詢中。此外,不會生成額外的查詢,只會添加子句。延期執行將它們放在一起。這種擴展'IQueryable'的方法是很常見的做法。 –

+0

你說的延遲執行是正確的,這就是爲什麼我沒有說你在每個If語句中訪問數據庫的原因,我不只是說三元運算符是If語句的一個不太冗長的形式。我一直使用它多年沒有抱怨,並認爲它應該用於任何時候你想保持簡單。 原因畢竟,如果你不得不建立一個複雜的IF - EndIF結構來獲得它,你爲什麼要在最後有一個乾淨的查詢? –

0

您可能想嘗試LinqKit。有了這個庫,你有一個PredicateBuilder類方法:

public static Expression<Func<T, bool>> True<T>(); 
public static Expression<Func<T, bool>> False<T>(); 
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2); 
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2); 

這些是Expression對象,這可以從lambda表達式可以輕鬆創建擴展。

有了這樣一個表達式,你可以做yourDataSource.Where(expression)

對不起,對於C#表示法,我不知道VB.net ... 如果有人想修復它到VB,感覺自由。

編輯:

嘛,PredicateBuilder只是一個整潔的語法糖。在他們的網站上你可以找到完整的源代碼,這非常簡單。不幸的是,在C#中。 這裏有雲:

using System; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Collections.Generic; 

public static class PredicateBuilder 
{ 
    public static Expression<Func<T, bool>> True<T>() { return f => true; } 
    public static Expression<Func<T, bool>> False<T>() { return f => false; } 

    public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
    var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>> 
      (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); 
    } 
} 

就是這樣!表達式(在.net中是標準的,不需要額外的庫)提供了一些很好的方法來處理它們,它們可以在where子句中使用。 試試看吧:)

+0

問題是我不允許使用額外的庫。儘管這對我的個人項目非常有用。非常感謝你。你可能還有其他答案嗎? – deltu100

+0

看看我的編輯然後:) –

+0

看看http://www.albahari.com/nutshell/predicatebuilder.aspx - 這是一個很好的解釋它是如何工作的。 –

0

你在正確的軌道與您的代碼上..你只需要改變if語句的Ternary Operator

Dim table = New Dictionary(Of Integer, String) 
    table.Add(1, "one") 
    table.Add(2, "two") 
    table.Add(3, "three") 

    Dim inputCol1 As Integer 
    Dim inputCol2 As String = "one" 

    Dim list = (From P In table Where _ 
       (inputCol1 < 1 OrElse P.Key = inputCol1) _ 
       And (inputCol2 = "" OrElse P.Value = inputCol2) _ 
       Select P).ToList() 

找到有關這個問題,這個情況的詳細信息:Conditional filtering