复杂的Linq表达式构建器

时间:2013-01-08 16:34:28

标签: c# linq linq-expressions

我需要构建一个可配置的查询构建器,允许用户复合任意数量的可能条件。例如,假设我们有CustomerOrderOrderItemProduct的经典案例。用户希望能够对包含3个以上项目的所有订单绘制报告。或者也许订单只有一个项目。基本上应该是相同的查询,除了比较器会有所不同。

用户可能还希望了解客户居住在区号10024中的情况。或者该订单至少包含/最多/正好2项产品ID 14.每个条件显然都需要硬编码它自己的方法,但每个条件的基本签名将是:

private static Expression<Func<Order, bool>> SomePredicate(object someParameters)

到目前为止,这就是我所描述的最后一个条件:

private static Expression<Func<Order, bool>> CountProductItems(int productID, int count, Comparator comparator) {
  Expression<Func<Order, int>> productOrderItems = 
    order => order.Items.Where(i => i.ProductID == productID)
                  .Sum(i => i.Quantity);
  switch (comparator) {
    case Comparator.Equals:
      // return... uh... now what?
    case Comparator.GreaterThan:
      // you get the picture....
  }
}

我只是错过了最后一个语法步骤:如何使用该表达式productOrderItems并返回表达式等于/小于/大于/ etc的顺序。提供的值count

你是怎么做到的?

2 个答案:

答案 0 :(得分:1)

使用Expression

,而不是使用方法中的Func个对象
Func<Order, int> productOrderItems =
    (Order o) => o.Items.Where(i => i.ProductID == productID)
                        .Sum(i => i.Quantity);

然后在switch内,您可以在productOrderItems之上撰写另一个Lambda表达式作为返回值。它将自动转换为Expression,因为ExpressionFunc在技术上可以互换:

switch (comparator) {
    case Comparator.Equals:
        return (Order o) => productOrderItems(o) == count;
        break;
    // etc.
}

答案 1 :(得分:0)

我已成功使用了ScottGu的Dynamic LINQ Query

在我们的例子中,我们需要在运行时定义Where子句,它就像魅力一样。

它还向here提供了附加信息。

有了这个,你可以做类似的事情:

var query = Northwind.Products.Where("CategoryID=2 And UnitPrice>3");