【问题标题】:IQueryable Where Extension Method with Or's [duplicate]IQueryable Where 扩展方法与 Or 的 [重复]
【发布时间】:2010-10-26 15:20:21
【问题描述】:

复制:

How to dynamically add OR operator to WHERE clause in LINQ

我想遍历一个字符串值数组并构建一个 linq 表达式

列表中的每个项目都是 OR'ed 在一起的。

string[] search = new string[]{"A", "B", "C"};
foreach (string item in filterValues)
{
    searchQuery = searchQuery.Where(s => s.Name.Contains(item));
}

上面的代码搜索“A”AND“B”AND“C”

我想搜索“A”OR“B”OR“C”。

我知道如何使用 Linq 做到这一点,但我想使用扩展方法完成同样的事情。

【问题讨论】:

  • 为什么不发布 linq sintax?
  • 您的代码不适用于 AND 案例。请参阅链接问题的答案和stackoverflow.com/questions/658818/linqtosql-strange-behaviour/…,因为它没有。您基本上在循环的每次迭代中都捕获了相同的变量。
  • 这是重复的...我搜索 stackoverflow 寻找答案...我想我的搜索技能需要改进。感谢您的帮助
  • 试试searchQuery.Where(s => search.Contains(s));

标签: c# linq iqueryable


【解决方案1】:
var filterValues = new[] { "A", "B", "C" };

var values =
    (from item in filterValues
     from value in searchQuery
     where value.Name.Contains(item)
     select value)
     .Distinct();

【讨论】:

    【解决方案2】:

    我今天为此苦苦挣扎。然后我终于意识到,如果我将数组变成一个字符串列表,我可以进行连接。一个 queryextender 控件 (.NET 4) 正在调用下面的函数。不要忘记订单...这很重要。不使用会报错。

        Protected Sub FilterTestType(ByVal sender As Object, ByVal e As CustomExpressionEventArgs)
        Dim _codes As List(Of String) = GetTestCodes()
        e.Query = From _tests In e.Query.Cast(Of LabTest)()
                  Join _code In _codes On _tests.TestCode Equals _code
                  Order By _tests.LoadDate Descending
                  Select _tests
    End Sub
    

    【讨论】:

      【解决方案3】:

      我喜欢这个解决方案:

      string[] search = new string[]{"A", "B", "C"};
      foreach (string item in filterValues)
      {
          searchQuery = searchQuery.Where(s => s.Name.Contains(item)).Concat(searchQuery);
      }
      

      在我的 MVC3 WebApp 上运行良好

      【讨论】:

      • 这会产生非常低效的SQL查询。
      【解决方案4】:

      我迟到了,但是……

      我最近创建了一个关于创建启用以下语法的 IQueryable 搜索扩展方法的博客:

      string[] search = new string[]{"A", "B", "C"};
      var searchQuery = context.Users.Search(u => u.Name, search); 
      

      更新:开始

      我已经更新了搜索扩展,这影响了搜索的执行方式以使用新的流畅 API。这意味着上面现在应该写成

      var searchQuery = context.Users.Search(u => u.Name)
                                     .Containing("A", "B", "C"); 
      

      更多关于新 api 的信息可以在这里看到:http://jnye.co/Posts/2030/searchextensions-search-strings-with-the-new-fluent-api

      更新:结束

      http://jnye.co/Posts/8/generic-iqueryable-or-search-for-multiple-search-terms-using-expression-trees

      https://github.com/ninjanye/SearchExtensions

      我还有一个可以从这里安装的 nuget 包:

      http://www.nuget.org/packages/NinjaNye.SearchExtensions/

      但是,如果您想自己执行此操作,则需要执行以下操作: 首先你需要创建扩展方法

      public static class QueryableExtensions  
      {  
          public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> stringProperty, params string[] searchTerms)  
          {  
              if (!searchTerms.Any())  
              {  
                  return source;  
              }  
        
              Expression orExpression = null;  
              foreach (var searchTerm in searchTerms)  
              {  
                  //Create expression to represent x.[property].Contains(searchTerm)  
                  var searchTermExpression = Expression.Constant(searchTerm);  
                  var containsExpression = BuildContainsExpression(stringProperty, searchTermExpression);  
        
                  orExpression = BuildOrExpression(orExpression, containsExpression);  
              }  
        
              var completeExpression = Expression.Lambda<Func<T, bool>>(orExpression, stringProperty.Parameters);  
              return source.Where(completeExpression);  
          }  
        
          private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)  
          {  
              if (existingExpression == null)  
              {  
                  return expressionToAdd;  
              }  
        
              //Build 'OR' expression for each property  
              return Expression.OrElse(existingExpression, expressionToAdd);  
          }  
      }
      

      然后可以按如下方式使用:

      string[] search = new string[]{"A", "B", "C"};
      var searchQuery = context.Users.Search(u => u.Name, search);  
      

      这将创建您所追求的或查询。

      希望这个答案仍然与您相关。

      【讨论】:

      • 感谢约翰·奈!多么优雅且功能齐全的解决方案。你开发的 NuGet 包太棒了!
      • 很高兴得到帮助并且您正在享受 nuget 包。很高兴听到它受到好评
      【解决方案5】:

      对于具有已知数量 where 选择的情况,一种方法是简单地收集要排除的列表,然后应用 where 方法。

      dim BASEQUERY = FROM blah in blahblahblah _
      WHERE ....
      select blah
      
      For Each item In EXCLUDELIST
      Dim sitem As String = item
      BASEQUERY = BASEQUERY.Where(Function(py) py.YOURCOLUMN <> sitem)
      Next
      

      这将只留下你想要的,它相当于一个复合“或哪里”条件。注意:大量排除的项目可能会异常缓慢。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多