gpt4 book ai didi

c# - 将 IQueryable Where() 扩展为 OR 而不是 AND 关系

转载 作者:太空狗 更新时间:2023-10-29 18:11:34 24 4
gpt4 key购买 nike

我正在使用我自己的 IQueryable<> 扩展方法来创建可链接的查询,例如 FindAll().FindInZip(12345).NameStartsWith("XYZ").OrderByHowIWantIt() 等,然后在延迟执行时创建单个查询基于我的扩展方法链。

不过,这个问题是扩展链中的所有 Where's(FindXYZ、FindInZip 等)将始终组合为 AND,这意味着我不能做这样的事情:

FindAll().FirstNameStartsWith("X").OrLastNameStartsWith("Z") 因为我不知道如何在单独的 Where 方法中注入(inject) OR。

知道如何解决这个问题吗?


额外的;到目前为止,我了解如何将表达式链接为 Or 如果我将它们包装起来(例如 CompileAsOr(FirstNameStartsWith("A").LastNameStartsWith("Z").OrderBy(..))

虽然我想要做的稍微复杂一些(PredicateBuilder 在这里没有帮助..)因为我想要一个稍后的 IQueryable 来基本上访问之前建立的 Where 条件,而不必包装它们来创建他们之间的或。

由于每个扩展方法都返回 IQueryable<> 我知道它应该了解某处查询条件的当前状态,这让我相信应该有一些自动化的方法或在所有先前的 Where 条件下创建一个 Or必须包装你想要的东西。

最佳答案

我假设查询的不同部分仅在运行时已知,即您不能只使用 ||where ...

一个懒惰的选项是 Concat - 但这往往会导致糟糕的 TSQL 等;但是,我倾向于写自定义 Expression相反。采取的方法取决于提供者是什么,因为 LINQ-to-SQL 支持不同的 EF 选项(例如)——这在这里具有真正的影响(因为您不能将子表达式与 EF 一起使用)。你能告诉我们是哪一个吗?


下面是一些应该与 LINQ-to-SQL 一起工作的代码;如果您构建一个表达式数组(或列表,并调用 .ToArray() ),它应该可以正常工作;示例是 LINQ-to-Objects,但应该仍然有效:

    static void Main()
{
var data = (new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }).AsQueryable();

var predicates = new List<Expression<Func<int, bool>>>();
predicates.Add(i => i % 3 == 0);
predicates.Add(i => i >= 8);

foreach (var item in data.WhereAny(predicates.ToArray()))
{
Console.WriteLine(item);
}
}

public static IQueryable<T> WhereAny<T>(
this IQueryable<T> source,
params Expression<Func<T,bool>>[] predicates)
{
if (source == null) throw new ArgumentNullException("source");
if (predicates == null) throw new ArgumentNullException("predicates");
if (predicates.Length == 0) return source.Where(x => false); // no matches!
if (predicates.Length == 1) return source.Where(predicates[0]); // simple

var param = Expression.Parameter(typeof(T), "x");
Expression body = Expression.Invoke(predicates[0], param);
for (int i = 1; i < predicates.Length; i++)
{
body = Expression.OrElse(body, Expression.Invoke(predicates[i], param));
}
var lambda = Expression.Lambda<Func<T, bool>>(body, param);
return source.Where(lambda);
}

关于c# - 将 IQueryable<T> Where() 扩展为 OR 而不是 AND 关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/930677/

24 4 0