OutOfMemoryException:在任务

时间:2016-09-13 07:57:24

标签: c# out-of-memory dbcontext

这是我目前正在处理的以下设置:

  • 我有一个带有~1.000.000条目的sql-table我需要更新
  • 更新发生在一个单独的线程中(由任务启动)
  • 由于内存在线程中受限,我每批处理1000个条目的列表     (在mainthread /没有任何任务的测试项目中运行时,没有OOM异常)
  • UpdateList()函数更新列表的字段或为DbContext中的此表或其他表创建新记录
  • Process_Failure()函数中,我有一个整个列表的单个上下文实例
  • Process_Success()函数中,我将while - 循环移到了上下文之外
private void Process_Success()
{
    var totalProcessedCounter = 0;

    while( true )
    {
        using( var context = new MyDbContext() )
        {
            var list = context.MyClass.OrderBy( x => x.Id )
                .Skip( totalProcessedCounter ).Take( 1000 )
                .ToList();

            if( !list.Any() )
                break;

            UpdateList( list );

            totalProcessedCounter += list.Count;
        }
    }
}

private void Process_Failure()
{
    var totalProcessedCounter = 0;

    using( var context = new MyDbContext() )
    {
        while( true )
        {
            var list = context.MyClass.OrderBy( x => x.Id )
                .Skip( totalProcessedCounter ).Take( 1000 )
                .ToList(); // throws OutOfMemoryException

            if( !list.Any() )
                break;

            UpdateList( list );

            totalProcessedCounter += list.Count;
        }
    }
}

private void UpdateList( List<MyClass> list )
{
    var doSaveChanges = false;

    list = list.Where( x => SomeFilter( x ) ).ToList();

    using( var context = new MyDbContext() )
    {
        foreach( var item in list )
        {
            ChangeItem( item );
        }

        if( doSaveChanges )
            context.SaveChanges();
    }
}

当我在context的嵌套功能调用中创建另一个实例时,获取UpdateList()以某种方式被污染/填充?

1 个答案:

答案 0 :(得分:2)

你得到异常的原因是因为DbContext缓存了the data you read from DB,所以如果你继续向其缓存中添加实体,你会在某些时候炸掉你的内存,你会得到{{1 }}。 GC不会清除实体,因为OutOfMemoryException引用了实体。

尝试使用DbContext

.AsNoTracking()

但是,如果您不跟踪实体,请更新它们is more difficult(读取“将现有实体附加到上下文”),因为这些实体不属于任何上下文且未被跟踪。

我不会像这样使用EF,这看起来像UPDATE / SELECT SQL语句的一个很好的任务。