我有一个在几个地方使用的Linq表达式。我走了表达路线,因为没有逻辑方法来完成一些搜索逻辑而不会枚举一个非常大的表。
private Expression<Func<Property, bool>> PropertyIsCompliant()
{
return (p) => p.CalculationSets.OfType<SingleDocumentCalculationSet>()
.GroupBy(cs => cs.SourceDocument)
.Select(g => g.OrderByDescending(d => d.DateTime).FirstOrDefault().CalculationResults)
.SelectMany(cr => cr)
.All(cr => cr.Outcome == CalculationOutcome.Success);
}
我的模型是这样的:
我正在尝试创建一个表达式,告诉我最近计算的所有结果是否按最近(即最近的不同结果)排序的文档分组是否成功。
我可以使用SelectMany子句从正确的CalculationSets返回所有CalculationResults。 我只是想知道如果集合不是空的,如果只返回true,它们都是Outcome.Success。
我理解All运算符会在空集合上自动返回true。我只是想不出办法来解决它!
答案 0 :(得分:3)
所以真正的条件是没有不成功的结果。在这种情况下,使用Any
并反转条件:
//V-- notice the ! inverse operator here
return (p) => !(p.CalculationSets.OfType<SingleDocumentCalculationSet>()
.GroupBy(cs => cs.SourceDocument)
.Select(g => g.OrderByDescending(d => d.DateTime).FirstOrDefault().CalculationResults)
.SelectMany(cr => cr)
.Any(cr => cr.Outcome != CalculationOutcome.Success));
答案 1 :(得分:1)
var countsBySuccess =
...
.GroupBy(cr => cr.Outcome == CalculationOutcome.Success) //group on success
.Select(g => new { IsSuccessful = g.Key, Count = g.Count() });
您现在可以检查两个结果行,以确保不成功的计数为零,并且成功计数为非零。
关于性能,这需要在服务器端实现整个结果集并对其进行聚合。但它只这样做了一次。
如果您必须将计算结果用作更大查询的一部分,则必须使用另一个技巧:
!countsBySuccess.Any(g =>
g.IsSuccessful && Count == 0 ||
!g.IsSuccessful && Count != 0)
此布尔表达式通过一次扫描数据来确定您要查找的条件是否成立。
仅扫描一次数据非常重要。 不只需写:
myItems.All(cr => cr.Outcome == CalculationOutcome.Success) && myItems.Any()
因为这会进行两次扫描。 SQL Server没有对此进行优化。
答案 2 :(得分:0)
我认为你正在回答你的问题 - 如果你知道All返回TRUE为空,那么你有两个检查要做。请原谅我的C#(我不确定var查询分配,希望你能得到这个想法),但你可以这样做:
private Expression<Func<Property, bool>> PropertyIsCompliant()
{
var query = (p) => p.CalculationSets.OfType<SingleDocumentCalculationSet>()
.GroupBy(cs => cs.SourceDocument)
.Select(g => g.OrderByDescending(d => d.DateTime).FirstOrDefault().CalculationResults)
.SelectMany(cr => cr);
return (query.Count > 0) & query.All(cr => cr.Outcome == CalculationOutcome.Success);
}
答案 3 :(得分:0)
我没有意识到可以使用“&amp;&amp;”在表达式中。所以我设法结合了两个单独的表达式,给出了我需要的答案。 “&amp;&amp;”只有当两个表达式都评估为“true”时才返回true
return (p) =>
p.CalculationSets.OfType<SingleDocumentCalculationSet>()
.GroupBy(cs => cs.SourceDocument)
.Select(g => g.OrderByDescending(d => d.DateTime).FirstOrDefault().CalculationResults)
.SelectMany(cr => cr).Any()
&&
p.CalculationSets.OfType<SingleDocumentCalculationSet>()
.GroupBy(cs => cs.SourceDocument)
.Select(g => g.OrderByDescending(d => d.DateTime).FirstOrDefault().CalculationResults)
.SelectMany(cr => cr)
.All(cr => cr.Outcome == CalculationOutcome.Success);