【问题标题】:Optimize/faster choice than "not all" in LINQ优化/比 LINQ 中的“不是全部”更快的选择
【发布时间】:2019-05-30 13:41:01
【问题描述】:

我正在使用 EF 6 和 .NET Framework 4.6.1。我有一个场景,如果父记录的所有子记录都满足特定条件,我需要排除它。

这是我迄今为止所做的通用版本:

public ParentRecords GetParentRecordsExceptWhereSpecificStringOnAllChildren(string aSpecificString){ 
        return ParentRecords
            .Where(parent => !parent.ChildRecords
                .Select(child => child.SomeStringProperty)
                .All(c => c.Equals(aSpecificString))
        );
    }

这需要一点时间来运行(以每个子记录一秒的规模),并且从 EF 生成的 SQL 包含 n-1 个UNION ALL 语句,其中 n 是子记录的数量。

我怀疑我错过了一种明显的方式来编写这个可以显着提高性能的方法,但我没有看到它(但无论如何我都不是 LINQ/EF 大师)。

我编写了一个存储过程,它返回相同的数据,但速度更快,而且布局不完全相同(一个平坦的行与每个子记录的一行)。不过,我们正试图避免存储过程,所以我回到了研究如何使这个 LINQ 更快的问题上。

任何建议将不胜感激。如果我没有解释清楚,请告诉我。为了重复使用,我试图使其通用,以防其他人处于这种情况。

【问题讨论】:

  • 如果至少有一条子记录不符合条件,我建议尝试排除一条记录:.Any(c => !c.Equals(aSpecificString))
  • 天哪,太完美了。谢谢!我试试看!
  • 这可能没什么区别,但你也不需要Select。你应该可以做到.Any(c => !c.SomeStringProperty.Equals(aSpecificString))
  • 哦。我也会试试的。到目前为止,这看起来要快得多(100 毫秒左右,而 5400 毫秒)。
  • @RomanKoliada 这要快得多,谢谢。我不完全确定为什么,因为生成的 SQL 仍然显示大量 UNION ALL 语句,但它肯定要快得多。如果您从评论中创建“答案”,我会将其标记为答案。

标签: c# performance entity-framework linq


【解决方案1】:

您可以从代码中删除对 SomeStringProperty 的选择。

使用任意

        ParentRecords.Where(parent =>
            parent.ChildRecords.Any(child => !child.SomeStringProperty.Equals(aSpecificString)));

全部使用

       ParentRecords.Where(parent =>
            !parent.ChildRecords.All(child => child.SomeStringProperty.Equals(aSpecificString)));

【讨论】:

  • 这些更改(删除 Select 并使用 Any 最终解决了我看到的性能问题,因此我将其标记为答案。
猜你喜欢
  • 2011-03-12
  • 1970-01-01
  • 2013-10-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-13
  • 1970-01-01
相关资源
最近更新 更多