【问题标题】:entity .ToList() generates a System.OutOfMemoryException实体 .ToList() 生成 System.OutOfMemoryException
【发布时间】:2014-09-17 21:03:34
【问题描述】:

我有一张有 50 万行的表格。我需要更新每一行,但 ToList() 失败:

List<Contacts> allContacts = objDatabase.Contacts.ToList();

我每次都会收到 System.OutOfMemoryException。有没有办法解决这个问题?

我已经有了 App.Config 解决方法,但还是不行:

<gcAllowVeryLargeObjects enabled="true" />    

我在一台 64 位机器上,有 8GB 内存

【问题讨论】:

  • 为什么你需要一次所有的 500,000 条记录?尝试将它们分成块,处理它们并获得另一个块。
  • 您是否尝试过使用foreach 循环逐一枚举项目,以便从数据库中逐一进行流式传输?无论哪种方式,在使用 ORM 时,一次处理 500,00 个项目是相当多的。
  • 即使您在 64 位计算机上,您也可能在 32 位进程中运行。一些项目模板的默认平台目标是 x86,或者启用了“首选 32 位”选项。如果您正在在 62 位进程中运行,则物理内存不足不会导致内存不足异常;内存被分页到磁盘,这通常会导致糟糕的性能。
  • 按照@brz 的建议,分块获取列表。使用 Skip() 和 Take(),每次卡盘后,确保处理并创建一个新的实体容器,这样你的内存就不会被用完。

标签: c# .net linq entity


【解决方案1】:

这是一个使用分块的解决方案。它将在每个块之后处理容器(和下载的实体)。 GC 应该在您的系统内存不足之前释放内存。

int chunkSize = 50;
int curCount = 0;

while (true)
{
    using (var db = new DbEntities())
    {
        var chunk = db.Contacts.Skip(curCount).Take(chunkSize).ToArray();
        curCount += chunkSize;

        if (chunk.Length == 0) break;

        foreach (var contact in chunk)
        {
            //do any work for the contact here
            contact.Something = "SomethingNew";
        }

        db.SaveChanges();
    }
}

随意调整块大小。 chunk 越大,整个过程应该越快,但是会占用更多的内存。

【讨论】:

  • 谢谢,我认为这是唯一的方法。 .NET 无法处理 50 万行,这有点奇怪,这是 2014 年......
  • 我必须在调用skip之前添加一个订单。除此之外,它完美无缺!
【解决方案2】:

怎么样

IEnumerable<Contacts> allContacts = objDatabase.Contacts.AsEnumerable();

永远不要将 allContacts 转换为列表。只需使用就像一个枚举器并应用 Foreach 循环来访问每个联系人。

【讨论】:

  • 这很好,但现在 SaveChanges() 中发生了同样的异常,我想我将不得不像其他建议的那样将处理分成块
  • 好的。现在明白了。我不喜欢笨拙的解决方案,但似乎这是目前唯一的方法。
【解决方案3】:

试试

foreach (Contacts c in objDatabase.Contacts) c.value = newvalue;

【讨论】:

  • 这仍然会导致所有可能的记录都被下载到本地内存。
  • 内森。 BS。那是一次一个记录。这就是 IEnumerable 的工作原理。
  • 你研究。一旦 foreach 开始,就会从数据库中提取整个结果集:stackoverflow.com/a/18216387/2465182。这将导致与 ToList() 一样多的内存使用量。
  • @NathanA Double BS 你读过那个答案吗?它使用 DataReader 一次提取一个结果(并保持连接)。这与从数据库中提取整个结果集之前不会开始前行不同。您一次使用它们,它们会耗尽内存。
  • 现在在 SaveChanges() 中发生异常,是时候将处理拆分成块了...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多