8

LINQ では、次のように段階的に LINQ クエリを作成できます。

var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// Step 2
query = query.Where(d => d.TerritoryID == 3);

上記のクエリは、次のようなAND論理演算子によって結合された 2 つの述語で構成される WHERE 句を含む同等の SQL ステートメントを生成します。

SELECT * FROM Customers WHERE CustomerType = 'Individual' AND TerritoryID = 3

次のように、 OR論理演算子progressivelyによって結合された述語を含む WHERE 句が結果のクエリに含まれるように、同等の SQL ステートメントを生成する LINQ クエリを作成できますか?

SELECT * FROM Customers WHERE CustomerType = 'Individual' OR TerritoryID = 3
4

4 に答える 4

19

最初にフィルターを作成してから、フィルターを組み合わせて、合成クエリとして使用できる単一のラムダにする必要があります。

var filters = new List<Expression<Func<YourType, bool>>>();
filters.Add(d => d.TerritoryID == 3);
filters.Add(d => d.CustomerType == "Individual");
...

var lambda = AnyOf(filters.ToArray());
// this is: d => d.TerrotoryID == 3 || d.CustomerType == "Individual";

var data = src.Where(lambda);

使用:

static Expression<Func<T,bool>> AnyOf<T>(
          params Expression<Func<T,bool>>[] expressions)
{
    if (expressions == null || expressions.Length == 0) return x => false;
    if (expressions.Length == 1) return expressions[0];

    var body = expressions[0].Body;
    var param = expressions[0].Parameters.Single();
    for (int i = 1; i < expressions.Length; i++)
    {
        var expr = expressions[i];
        var swappedParam = new SwapVisitor(expr.Parameters.Single(), param)
                            .Visit(expr.Body);
        body = Expression.OrElse(body, swappedParam);
    }
    return Expression.Lambda<Func<T, bool>>(body, param);
}
class SwapVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public SwapVisitor(Expression from, Expression to){
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}
于 2013-03-28T08:54:08.723 に答える
1

2 つのステップでそれが必要な場合は、ユニオンを使用できます。


var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// step2 
query = query.Union(context.Customers.Where(d => d.TerritoryID == 3));

于 2013-03-28T08:56:20.467 に答える
0

動的な linq ライブラリを使用せずに要求を達成するには、where 句で各テストの式を定義し、それらを使用してラムダ式を作成します。

Expression<Func<Customer, bool>> isIndividualCustomer = c => c.CustomerType == "Individual";

Expression<Func<Customer, bool>> territoryIdIs3 = c => c.TerritoryID == 3;

Expression<Func<Car, bool>> customerIsIndividualOrOfTerritoryId3 = Expression.Lambda<Func<Customer, bool>>(
    Expression.Or(isIndividualCustomer.Body, territoryIdIs3.Body), isIndividualCustomer.Parameters.Single());

使用法:

var query = context.Customers.Where(customerIsIndividualOrOfTerritoryId3);
于 2013-03-28T09:06:01.283 に答える
0

この種のことを直接行うこともできますが、私はこのような漸進的なクエリの構築を非常に簡単にする LinqKit ライブラリを使用します。

最終的には次のようになります。

var context = new AdventureWorksDataContext();
// Step 1
var query = context.Customers.Where(d => d.CustomerType == "Individual");
// Step 2
query = query.Or(d => d.TerritoryID == 3);

私が取り組んでいるシステムにはこれがたくさん必要で、LinqKit は大きな命の恩人です。ここで見つけることができます。

(注: とにかく、私は LinqKit の開発者と提携していません - ただのファンです。)

于 2013-03-28T09:12:27.910 に答える