我正在试图弄清楚如何使用PredicateBuilder来确定Expression中是否存在一组特定的记录。因此,给定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)将结果计数与规格计数进行比较。所有这些都可以在Expression之外完成,但是有一种优雅的方法来评估Expression中的所有内容,结果是一个布尔值吗?
也就是说,我想让Expression自包含,以便它可以按原样传递,而我给它的那些不必知道如何进行“后处理”来弄清楚如果它是真的。
答案 0 :(得分:0)
对于你给出的例子,我相信你可以通过不同的方式更简单地做到这一点。
不要使用OrderDetails,而是从规范开始,确保它们在OrderDetails集合中都是All。这一行代码将满足您确保特定orderID包含所有规范的要求,并且它并不复杂:
bool containsAllSpecs = specs.All
(s => orderDetails.Any (p => p.OrderId == orderId && p.ProductId == s));
我认为,尝试在OrderDetail类中构建Expression是不可能的,因为表达式仅应用于整个集合中的单个项目,因此不知道集合中的其他项目。
如果你真的想创建一个扩展来隐藏尽可能多的逻辑,你可以把它放在一个扩展中:
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);