以下是我目前处理的设置:
- 我有一个包含大约1,000,000条记录的SQL表需要更新
- 更新在单独的线程中进行(由任务启动)
- 由于线程内存有限,我将列表分批处理,每批1000个条目 (在主线程/没有任何任务的测试项目中运行时,不会出现OOM异常)
UpdateList()
函数可以更新列表字段或为此或其他表创建新记录- 在
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();
}
}
当我在UpdateList()
的嵌套函数调用中创建另一个实例时,是否会以某种方式污染/填充context
?
.ToList()
。这会执行查询并将所有东西倾倒到内存中。移除它,.Any()
将在没有它的情况下正常工作。 - Mike Eason.ToList()
并跳过该行,将光标悬停在list
变量上,您应该会在展开器中看到一个 结果视图。这将执行查询,您将能够查看结果。或者您可以使用 立即窗口 并在那里执行查询:list.ToList()
应该打印出结果。 - Mike Eason