首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >DbContext OutOfMemoryException

DbContext OutOfMemoryException
EN

Stack Overflow用户
提问于 2015-08-23 01:21:33
回答 4查看 600关注 0票数 4

我有一个数据集大于20m记录的DbContext,它必须转换成不同的数据格式。因此,我将数据读入内存,执行一些任务,然后释放DbContext。代码运行良好,但过一段时间我就会得到OutOfMemoryExceptions。我已经能够将其缩小到下面的代码段,在该代码中,我检索了200万条记录,然后释放它们并再次获取它们。第一次检索工作很好,第二次则抛出异常。

代码语言:javascript
复制
// first call runs fine
using (var dbContext = new CustomDbContext())
{
    var list = dbContext.Items.Take(2000000).ToArray();
    foreach (var item in list)
    {
        // perform conversion tasks...
        item.Converted = true;
    }
}

// second call throws exception
using (var dbContext = new CustomDbContext())
{
    var list = dbContext.Items.Take(2000000).ToArray();
    foreach (var item in list)
    {
        // perform conversion tasks...
        item.Converted = true;
    }
}

GC不应该自动释放在第一个使用块中分配的所有内存,这样第二个块就应该像第一个块一样好地运行吗?

在我的实际代码中,我不是一次检索200万条记录,而是在每次迭代中检索0到30K之间的记录。然而,在大约15分钟后,我耗尽了内存,尽管所有的对象都应该已经释放了。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-08-24 20:17:03

重构之后,内存就会被释放。我不知道为什么,但很管用。

代码语言:javascript
复制
private static void Debug()
{
    var iteration = 0;
    while(true)
    {
        Console.WriteLine("Iteration {0}", iteration++);
        Convert();
    }
}

private static void Convert()
{
    using (var dbContext = new CustomDbContext(args[0]))
    {
        var list = dbContext.Items.Take(2000000).ToList();
        foreach (var item in list)
        {
            item.Converted = true;
        }
    }
}

当我在Debug()中将转换()的内容移动到while循环时,就会抛出OutOfMemoryExceptions。

代码语言:javascript
复制
private static void Debug()
{
    var iteration = 0;
    while(true)
    {
        Console.WriteLine("Iteration {0}", iteration++);
        using (var dbContext = new CustomDbContext(args[0]))
        {
            // OutOfMemoryException in second iteration
            var list = dbContext.Items.Take(2000000).ToList(); 
            foreach (var item in list)
            {
                item.Converted = true;
            }
        }
    }
}
票数 0
EN

Stack Overflow用户

发布于 2015-08-23 03:01:01

我猜你见过陆。可能你的对象比三重空间大,而且它们正在到达那里,因此GC在默认情况下是没有帮助的。

试试这个:https://www.simple-talk.com/dotnet/.net-framework/large-object-heap-compaction-should-you-use-it/

看看你的例外会不会消失。

即在第一部分和第二部分之间添加以下内容:

代码语言:javascript
复制
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect(); 
票数 1
EN

Stack Overflow用户

发布于 2015-08-23 07:09:00

IEnumerable有GetEnumerator(),所以您可以尝试这样做,以避免.ToArray()或.ToList() --如果您只想阅读:

代码语言:javascript
复制
// first call
using (var dbContext = new CustomDbContext())
{
    foreach (var item in dbContext.Items.Take(2000000))
    {
        // perform conversion tasks...
        item.Converted = true;
    }
}

// second call
using (var dbContext = new CustomDbContext())
{
    foreach (var item in dbContext.Items.Take(2000000))
    {
        // perform conversion tasks...
        item.Converted = true;
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32162321

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档