2012-09-26 27 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