簡體   English   中英

如何在LINQ中建立動態OR查詢?

[英]How to build up a dynamic OR query in LINQ?

我正在嘗試動態創建帶有鏈接的where子句。 現在,創建諸如SELECT Product WHERE x = 123 AND y = 349 AND w = 948的東西就沒問題了。 我只是添加額外的Where過濾器。 products = products.Where(product => product.Property == 123);

但是現在我有一個未知數量的值,應該使用OR運算符進行測試。 SQL應該類似於SELECT Product WHERE x = 123 OR x = 499 OR x = 998 .. and n more OR's

建立數字列表以進行檢查並執行以下操作:

var idsToCheck = new List<int>{123, 789, 654}; //Build from dynamic list
products = products.Where(x => idsToCheck.Contains(x.Id));

如果需要,可以將上面的v和w復制

var idsToCheck = new List<int>{123, 789, 654}; //Build from dynamic list
products = products.Where(x => idsToCheck.Contains(x.Id));

var propertyToCheck = new List<int>{123, 789, 654};//Build from dynamic list
products = products.Where(x => propertyToCheck.Contains(x.Property));

var numberToCheck = new List<int>{123, 789, 654};
products = products.Where(x => numberToCheck.Contains(x.Number));

如果要檢查的值已經作為枚舉數傳遞,則無需構建xxxToCheck集合。 你可以簡單地做.Contains對原稿

您可以在列表上使用contains或僅具有以下等式:

  products.Where(product => (product.Property == 123) || (product.Property == 499) || (product.Property == 998));

如果要從多個where子句組成一個OR查詢,則實際上需要在where子句中組成謂詞。 畢竟,將where子句鏈接為AND。

因此,如果您具有以下謂詞:

Func<Product, bool> w1 = p => p.x == 123;
Func<Product, bool> w2 = p => p.y == 349;
Func<Product, bool> w3 = p => p.w == 948;
Func<Product, bool> w4 = p => p.Property == 123;
Func<Product, bool> w5 = p => p.x == 499;
Func<Product, bool> w6 = p => p.x == 998;

您可以定義以下擴展方法以對其進行“或”操作:

public static Func<T, bool> Or<T>(this Func<T, bool> @this, Func<T, bool> that)
{
    return t => @this(t) || that(t);
}

現在您可以寫:

var products1 = products.Where(w1.Or(w5).Or(w6));

var products2 = products.Where(
    ((Func<Product, bool>)(p => p.x == 123))
        .Or(p => p.y == 349)
        .Or(p => p.Property == 123));

如果要使用子句列表,請添加此擴展方法:

public static Func<T, bool> Or<T>(this IEnumerable<Func<T, bool>> @this)
{
    return @this.Aggregate((Func<T, bool>)(t => true), (a, t) => a.Or(t));
}

現在您可以編寫:

var predicates = new List<Func<Product, bool>>()
{
    p => p.x == 123,
    p => p.w == 948,
    p => p.Property == 123,
    p => p.x == 998,
};

var products3 = products.Where(predicates.Or());

如果要針對IQueryable<T>提供程序編寫此代碼,則需要使用Expression<Func<Product, bool>> ,而不僅僅是Func<Product, bool>

然后,您需要以下擴展方法:

public static Expression<Func<T, bool>> Or<T>(
    this Expression<Func<T, bool>> @this,
    Expression<Func<T, bool>> that)
{
    var param =
        Expression
            .Parameter(typeof(T), "t");
    var body =
        Expression
            .Or(
                Expression
                    .Invoke(@this, param),
                Expression
                    .Invoke(that, param));
    return
        Expression
            .Lambda<Func<T, bool>>(body, param);
}

public static Expression<Func<T, bool>> Or<T>(
    this IEnumerable<Expression<Func<T, bool>>> @this)
{
    return @this.Aggregate((Expression<Func<T, bool>>)(t => true), (a, t) => a.Or(t));
}

調用代碼仍然起作用:

var predicatesX = new List<Expression<Func<Product, bool>>>()
{
    p => p.x == 123,
    p => p.w == 948,
    p => p.Property == 123,
    p => p.x == 998,
};

var products3X = products.Where(predicatesX.Or());

這是您要找的東西嗎?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM