0

通过 WCF 数据服务从客户端查询子实体时,.All()查询返回没有子实体的基本实体。例如,想象一个只有两个客户的数据库。订单是具有 BuyerName 列的子实体。一个客户记录有来自两个不同买家的两个订单,而另一个客户没有订单。

以下查询不会返回有两个订单的客户,因为他们是两个不同的买家(这是预期的)但它确实返回了没有任何订单的客户!

query.Where(c => c.Orders.All(
            o => o.BuyerName == buyer.Name));

通过添加一个额外的.Any()查询,我得到了我认为.All()查询会自动为我完成的事情。

query.Where(c => c.Orders.All(
            o => o.BuyerName == buyer.Name)
            && c.Orders.Any());

这似乎违反了最小意外原则。我认为调用.All()将要求在不存在子实体时不返回基本实体。.All()那么,当没有子实体存在时,为什么在 WCF 数据服务客户端返回基本实体?

4

1 回答 1

3

暂时忘记 OData 和 WCF 数据服务。这段代码应该产生什么?

IEnumerable<string> emptyEnumerable = Enumerable.Empty<string>();
bool result = emptyEnumerable.All(item => item == "foo");

如果我正确理解了您的问题,那么您会result认为是错误的,因为列表中没有任何项目。但result实际上会是真的。在MSDN 文档中,您可以看到 的返回值.All()记录为

“如果源序列的每个元素都通过了指定谓词中的测试,或者如果序列为空,则为true;否则为 false。”

据我所见,这是任何All()存在类似事物的语言的行为(我敢打赌,谓词逻辑的基础中有些东西需要这样做)。

因此,考虑到这一点,WCF 数据服务和 OData 正在做完全正确的事情,并遵循在其他地方使用的相同合同。c.Orders.All(predicate)如果c.Orders为空,则应始终返回 true。c在您的第一个查询中,这意味着任何c.Orders为空的内容都将通过过滤谓词。c.Orders就像您提到的那样,您可以通过要求c.Orders.Any()也为真来断言至少有一个项目来使过滤谓词更强。

于 2013-04-27T21:33:27.017 回答