迭代大型数据集时出现OutOfMemoryException

时间:2016-10-10 12:55:13

标签: c# .net memory

我有一个大约100,000行的表(而且它会变得更大)。

当我在循环中达到80,000条记录时,我的代码现在抛出OutOfMemoryException(即使我的系统当时有超过10gb的空闲时间,看起来视觉工作室仅限于1.5gb左右)。

代码旨在循环遍历所有记录,只检查某些条件。我拿出了实际处理记录的代码,内存仍然填满。

using (var db = new PlaceDBContext())
{
    Messages.Output("Total: " + db.Companies.Count());
    int count = 0;
    foreach (var company in db.Companies)
    {

        // I am not actually doing anything here,
        // I took out my code and the memory still fills up
        // CheckMatchConditions(company);

        count++;

        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(count.ToString() + "          ");

    }

}

我认为这可能与保持上下文打开有关,所以我重构了代码,一次只需要记录1,000条记录,然后将它们全部枚举到列表中。这就是我想出的:

int count = 0;
int total = 0;
using (var db = new PlaceDBContext())
{
    Messages.Output("Total: " + db.Companies.Count());
    total = db.Companies.Count();
}
while (count < total)
{
    List<Company> toMatch = new List<Company>();
    using (var db = new PlaceDBContext())
    {
        toMatch = db.Companies.Include(x => x.CompaniesHouseRecords).OrderBy(x => x.ID).Skip(count).Take(1000).ToList();
    }

    foreach (var company in toMatch)
    {

        // CheckMatchConditions(company);

        count++;

        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(count.ToString() + "          ");

    }
}

这种方法运行得慢得多,但仍然以大约相同的记录循环速度填充内存。

当我评论出我的实际方法时,它必须只是这些toMatch列表在内存中挥之不去。

我在这里不知所措,有人能说明我应该如何管理记忆吗?

2 个答案:

答案 0 :(得分:3)

添加。AsNoTracking(),确保DbContext不跟踪实体。

using (var db = new PlaceDBContext())
{
    Messages.Output("Total: " + db.Companies.Count());
    int count = 0;
    foreach (var company in db.Companies.AsNoTracking())
    {
        count++;
        Console.SetCursorPosition(0, Console.CursorTop);
        Console.Write(count.ToString() + ". company : " + company.someProp);
    }
}

答案 1 :(得分:0)

不要遍历对象集合,因为EF跟踪会因为您将实体选择到对象中而发生更改。 通过一些DTO迭代。

db.Companies.Select(c => new CompanyDto{ Name = c.Name});

但最好不要遍历整个数据集合。只是尝试在LINQ中编写检查条件方法,以允许SQL服务器进行过滤。