1

我试图弄清楚如何使用 PredicateBuilder 来确定一组特定的记录是否全部存在于一个表达式中。因此,给定一个 OrderId 和一个 ProductIds 列表作为规范,我想知道 Order 的 OrderDetail 记录是否包含所有规范项。不只是其中一个或一些——而是所有这些。

所以我可以这样做:

var inner = PredicateBuilder.False<OrderDetail>();

foreach (int spec in specs)
{
   temp = spec;            
   inner = inner.Or(d => d.ProductId == temp);
}

var outer = PredicateBuilder.True<OrderDetail>();

outer = outer.And(d => d.OrderId == orderId);
outer = outer.And(inner);

但是,在得到结果之后,我必须 a) 消除重复项(因为在我的情况下,多个 OrderDetails 可以具有相同的 ProductId),然后 b) 将结果计数与规范计数进行比较。所有这些在表达式之外都是可行的,但是有没有一种优雅的方法来评估表达式中的所有内容,使得结果是布尔值?

也就是说,我希望表达式是自包含的,以便它可以按原样传递,而我给它的那些不必知道如何进行“后期处理”来确定它是否真实.

4

1 回答 1

0

对于您给出的示例,我相信您可以通过不同的方式来简化它。

与其从您的 OrderDetails 开始工作,不如从您的规范开始,并确保它们都在 OrderDetails 集合中。这行代码将满足您确保特定 orderID 包含所有规范的要求,并且一点也不复杂:

bool containsAllSpecs = specs.All 
    (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s));

我认为尝试从 OrderDetail 类中构建表达式的原因是表达式仅应用于整个集合中的单个项目,因此不知道集合中的其他项目。

如果你真的想创建一个扩展来隐藏尽可能多的逻辑,你可以把它放在一个扩展中:

static class MyExtensions
{
    public static bool ContainsAllSpecs(this IEnumerable<OrderDetail> orderDetails,
        int orderId,
        IEnumerable<int> specs)
    {
        return specs
         .All (s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s));
    }
}

然后你可以从如下代码中调用它:

bool containsAllSpecs = orderDetails.ContainsAllSpecs(orderId, specs);
于 2012-06-17T18:22:36.520 回答