【问题标题】:System.OutOfMemoryException when trying to use ToDictionary on a LINQ Query尝试在 LINQ 查询上使用 ToDictionary 时出现 System.OutOfMemoryException
【发布时间】:2014-06-12 20:27:05
【问题描述】:

我正在尝试从具有 600 万条记录的销售表中填充字典对象。这是因为原始 linq 查询超时。我将 3 或 4 个表加入到销售表中,它太多了并且超时了。我以为我可以在内存中获取销售表,以防止 sql server 超时。

我的代码是:

var sales = dc.Sales
    .Where(c => c.Active == true)
    .Select(s => s)
    .ToDictionary(s => s.Id, s => s);

有谁知道如何在不引发内存不足异常的情况下填充我的字典对象?

【问题讨论】:

  • 所以你有这么多数据查询超时,你正试图将所有内容加载到内存中来解决这个问题?这其中的逻辑在哪里?
  • 为什么不尝试在每个查询中提取固定数量的记录(如 (10000))并维护一个每次递增的序列计数器以帮助您获取下一批记录
  • 我理解,但大多数时候我们将数据加载到字典中以加快应用程序的速度,然后将字典连接在一起并提取数据。我们在内存中做大部分事情。这通常有效,但这是我第一次达到 600 万条记录,所以我试图找出一种方法来完成这项工作。我们通常不会在团队中使用存储过程——我们通常使用 linq to sql 并在内存中完成大部分工作。这可能不是我想要做的,但想看看是否有人遇到过类似的情况并可以提供一些建议。感谢您的任何意见!
  • 购买更多内存 :-)。开个玩笑,这永远不会有效。你需要做任何你想做的小批量的事情。

标签: c# linq exception dictionary


【解决方案1】:

这个问题暗示了对数据库查询工作原理的严重误解。通常,当查询超时时,您必须限制提取的数据。如果你真的要拉这么多数据(我认为这是业务需求的错误),那么你应该分批拉它们。

我们通常使用 linq to sql

Linq-to-SQL 已经贬值多年了。它实际上无法创建可用的 SQL 查询。这可能就是您收到超时的原因。我认为 LINQ-to-SQL 不仅是一个糟糕的选择,而且完全风险等同于在您的软件中准备爆炸。您应该使用 LINQ-to-Entities 迁移到实体框架,或者使用手工制作的 SQL。这暗示了第二个问题:

我们将数据加载到字典中以加快应用程序的速度,然后将字典连接在一起并提取数据

我从未听说有人会使用这种方法或认为它可以使用。 SQL 可以轻松快速地完成此操作。如果您的团队真的认为这是做事的方式,那么需要认真学习 SQL。

【讨论】:

    【解决方案2】:

    感谢大家的反馈。我发现了导致内存不足异常的原因。我决定不使用字典,因为它不起作用。我去了 sql server 并复制了我的 linq 查询并运行它,但只得到了 30,000 条记录。所以我知道 linq 查询不会导致内存不足。我最初的查询只是使用一些 .Where() 子句对数据库进行简单的查找。事实证明,我正在对填充了 30,000 条记录的集合执行 .Distinct() ,这导致了内存不足异常。我删除了 .Distinct() 对 linq 查询的调用并修复了它。内存不足异常是有道理的,因为它试图处理集合中的 30,000 条记录并将它们区分开来,而且要比较的东西太多了。

    【讨论】:

    • 我不明白为什么 Distinct on 30k 记录会失败。你有任何文件来支持这个假设吗?
    【解决方案3】:

    我建议使用 ctx.Configuration.LazyLoadingEnabled = true;启用延迟加载,然后当需要数据时,将自行加载所需的实体。如果您不关闭上下文并再次打开,则加载的实体可以保留在上下文中并重复使用。 我已经尝试了包含 100000 个实体的程序,并使用延迟加载允许立即打开所需的对象。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 1970-01-01
      • 2018-04-30
      • 2015-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多