如何在linq中多次调用.where()方法以类似于OR(||)

本文关键字:方法 类似于 OR where 调用 linq | 更新日期: 2023-09-27 18:18:59


我试图创建一个类,允许我通过使用。where()方法在运行时配置LINQ查询,完成我的类后,而测试结果不像我预期的那样,所以我有一个问题,并解决我需要调用多个。where()方法的时间,它应该像OR一样,而不是像and &&
示例:

class Program
{
    private static string WhereTest()
    {
        string result = "";
        // List
        string[] lst = { "Sa", "Su", "Mo", "Tu", "We", "Th", "Fr" };
        // test 1
        var q1 = from l in lst
                 where l.StartsWith("S") && l.EndsWith("u")
                 select l;
        result = "1st query count: " + q1.Count() 
            + "'n----------------- 'nItems: 'n------- 'n";
        foreach (var item in q1.ToList())
        {
            result += item + "'n";
        }
        result += "'n";
        result += "'n";
        // test 2
        var q2 = from l in lst
                 where l.StartsWith("S") || l.EndsWith("u")
                 select l;
        result += "2nd query count: " + q2.Count() 
            + "'n----------------- 'nItems: 'n------- 'n";
        foreach (var item in q2.ToList())
        {
            result += item + "'n";
        }
        result += "'n";
        result += "'n";
        // test 3
        var q3 = from l in lst
                 select l;
        if (true)
            q3 = q3.Where(l => l.StartsWith("S"));
        if (true)
            q3 = q3.Where(l => l.EndsWith("u"));
        result += "3rd query count: " + q3.Count() 
            + "'n----------------- 'nItems: 'n------- 'n";
        foreach (var item in q3.ToList())
        {
            result += item + "'n";
        }
        result += "'n";
        result += "'n";

        return result;
    }
    static void Main(string[] args)
    {
        Console.WriteLine(WhereTest());
    }
}


结果:

<>之前第一次查询计数:1-----------------项目:-------苏第二次查询计数:3-----------------项目:-------Sa苏你第三次查询次数:1-----------------项目:-------苏之前在我的示例中,q3返回与q1相同的结果
所以我需要知道是否能让q3返回和q2相同的结果。
关于

如何在linq中多次调用.where()方法以类似于OR(||)

对于LINQ to SQL或其他基于查询的提供程序,PredicateBuilder是解决方案。它不允许您多次调用Where,但它允许您使用多个调用动态创建谓词。

对于LINQ to Objects,您可以使用委托而不是表达式树创建自己的PredicateBuilder等效物,如本答案所示。为了使这个答案完整,这里再写一遍相同的代码:

public static class DelegatePredicateBuilder
{
  public static Func<T, bool> True<T>()  { return f => true;  }
  public static Func<T, bool> False<T>() { return f => false; }
  public static Func<T, bool> Or<T>(this Func<T, bool> expr1,
                                     Func<T, bool> expr2)
  {
      return t => expr1(t) || expr2(t);
  }
  public static Func<T, bool> And<T>(this Func<T, bool> expr1,
                                     Func<T, bool> expr2)
  {
      return t => expr1(t) && expr2(t);
  }
}

你可以这样写:

var predicate = DelegatePredicateBuilder.False<string>();
if (someCondition)
{
    predicate = predicate.Or(l => l.StartsWith("S"));
}
if (someCondition)
{
    predicate = predicate.Or(l => l.EndsWith("u"));
}
query = query.Where(predicate);

System.Linq.Expressions

// List
string[] lst = { "Sa", "Su", "Mo", "Tu", "We", "Th", "Fr" };
Expression<Func<string, bool>> expr1 = t => t.StartsWith("S");
Expression<Func<string, bool>> expr2 = t => t.EndsWith("u");
var filter = new List<Expression>();
if (true)
{
    filter.Add(expr1);
}
if (true)
{
    filter.Add(expr2);
}
var input = Expression.Parameter(typeof(string), "input");
var result = Expression.Parameter(typeof(bool), "result");
var blockExpression = Expression.Block(
    new[] { result },
    Expression.Assign(result, Expression.Or(Expression.Invoke(expr1, input), Expression.Invoke(expr2, input)))
    );
var x = Expression.Lambda<Func<string, bool>>(blockExpression, new[] { input });
var func = x.Compile();
var res = lst.Where(func);

foreach (var re in res)
{
    Console.WriteLine(re);
}

你可以这样做。

q3 = q3.Where(l => l.EndsWith("u") || l => l.StartsWith("S")); 

如果你正在寻找动态的方式来构建查询下面的链接有谓词生成器可以帮助你。

http://www.albahari.com/nutshell/predicatebuilder.aspx