【问题标题】:c# linq where on object lists incredibly slowc# linq where on object lists 非常慢
【发布时间】:2019-08-30 16:08:32
【问题描述】:

我有一个看起来像这样的设置

foreach(Master m in masters){
   m.details = allDetails.Where(d => d.ID == m.detailID).ToList();
}

masters 和 AllDetails 只是对象列表,这里没有运行实际的 SQL。我早些时候这样做了。我实际上并没有写一个“正常”的 sql 连接查询,因为我希望这种方式会相当快......

这运行速度非常慢,例如 20 秒以上的 20k 主条目。

我知道我一定遗漏了一些非常明显的东西,但我就是不知道是什么。有什么办法可以解决这个超常见的问题?

【问题讨论】:

  • 选择在数据库中运行的位置会快得多。而且,据我们所知,您还没有实现allDetails,因此,对于每个大师,您都在访问数据库。为防止这种情况,当您创建 allDetails 时,请在可查询对象上执行 .ToArray()。
  • 我认为正常的连接会很快,因为它会创建一个主 ID 哈希和一个 allDetails 哈希。仅当您没有足够的内存时,连接才会运行缓慢。

标签: c# linq master-detail


【解决方案1】:

对于每个Master,您将遍历整个allDetails 列表。您应该使用分组并创建字典:

var detailsPerMaster = allDetails.GroupBy(d => d.ID)
                                 .ToDictionary(g => g.Key, g => g.ToList());

然后你可以设置你的details属性:

foreach(Master m in masters)        
    m.details = detailsPerMaster[m.detailID];

或者为了更好地匹配您的结果:

foreach(Master m in masters)            
    m.details = detailsPerMaster.TryGetValue(m.detailID, out var list) ? list : new List<--detailTypeHere-->();

【讨论】:

  • 天哪,这将我的时间从 20000 毫秒提高到了 6.6。那么这里的教训是什么?如果我更喜欢在 c# 而不是 sql 中加入我的对象,请始终查询字典?如果我知道关系是 1-1 有区别吗?
  • @DFENS 从您的问题来看,尚不清楚哪个部分已执行或可由数据库执行。无论如何,您的代码中的主要问题是您一次又一次地为每个主人迭代整个细节集合。在可能的解决方案中,您只在构建组时迭代细节一次。因此,无论是由数据库还是您的客户完成,您都可以获得性能。字典只是为了有一种简单的方法将结果传播到主实例中。
  • 字典也增加了很好的性能。我检查了普通的 FirstOrDefault 与创建字典的对比,它的速度大约快了 4 倍。我想对我来说主要的收获是尽可能避免去哪里。如果有任何事情需要花费几秒钟,那我很可能会做错事。
猜你喜欢
  • 1970-01-01
  • 2014-12-31
  • 2012-12-19
  • 2019-01-17
  • 1970-01-01
  • 1970-01-01
  • 2013-04-10
  • 2018-02-07
  • 1970-01-01
相关资源
最近更新 更多