C# 大数据表始终引发System.outofmemory异常

C# 大数据表始终引发System.outofmemory异常,c#,ado.net,C#,Ado.net,我有一个大型数据表,其中包含大约500000行。我必须遍历该数据表,并在每一行上应用业务逻辑。 问题是,在对庞大的数据表进行一定程度的迭代之后,它会抛出System.OutofMemory异常 dt是包含500000条记录的数据表。 我尝试了以下方法: int pageNum = 1; int pageSize = 10000; Datatable dtPage = null; DataModel model = null; //DataModel is a class containing

我有一个大型数据表,其中包含大约500000行。我必须遍历该数据表,并在每一行上应用业务逻辑。 问题是,在对庞大的数据表进行一定程度的迭代之后,它会抛出System.OutofMemory异常

dt是包含500000条记录的数据表。 我尝试了以下方法:

int pageNum = 1;
int pageSize = 10000;
Datatable dtPage = null;
DataModel model = null;
//DataModel  is a class containing various properties 
//i.e public class DataModel
//{
//  public string Name {get;set;}
 // public string Role {get;set;}
//etc....
//}

while(dt.Rows.Count  - (pageNum * pageSize ) > 0)
{
 dtPage = dt.Rows.Cast<System.Data.DataRow>().Skip((pageNum -1 ) *   pageSize).CopyToTable();
foreach(DataRow row in dtPage.Rows)
{
model = new DataModel();
PropertyInfo[] properties = typeof(DataModel).GetProperties();
foreach(PropertyInfo property in properties)
{
if(dtPage.Columns.Contains(property.Name))
 SetNewValue(model,property.Name,row[property.Name]);
}
if(model! = null) lst.Add(model);
}
pageNum ++;
}
intpagenum=1;
int pageSize=10000;
数据表dtPage=null;
DataModel=null;
//DataModel是一个包含各种属性的类
//i、 公共类数据模型
//{
//公共字符串名称{get;set;}
//公共字符串角色{get;set;}
//等等。。。。
//}
而(dt.Rows.Count-(pageNum*pageSize)>0)
{
dtPage=dt.Rows.Cast().Skip((pageNum-1)*pageSize.copytable();
foreach(dtPage.Rows中的数据行)
{
model=新数据模型();
PropertyInfo[]properties=typeof(DataModel).GetProperties();
foreach(属性中的PropertyInfo属性)
{
if(dtPage.Columns.Contains(property.Name))
SetNewValue(model、property.Name、row[property.Name]);
}
如果(model!=null)lst.Add(model);
}
pageNum++;
}

在这种情况下使用什么?我也尝试过MoreLinq的批处理方法,但仍然没有任何运气。

这行代码如何

if(model! = null) lst.Add(model);
我怀疑这是您的罪魁祸首,因为您正在继续向循环范围之外的变量添加项(这导致了一个问题,如果您所做的只是将所有内容都转储到同一个列表中,那么为什么还要处理所有复杂的分页逻辑呢)

您正在迭代一个有50万行的datatable,将其重新转换为每个页面的IEnumerable,使用反射来迭代DataModel对象,使用反射来设置属性,然后将新对象存储在集合中。当您在表上迭代时,内存使用确实会继续增长,因为您在每次迭代中都会创建新对象

从性能和内存的角度来看,这种方法都是不切实际的。考虑以下事项:

  • 只将datatable强制转换为IEnumerable一次,并将其存储在变量中,这样就不会每次都重新转换
  • 不要在这样的大循环中使用反射。我不是反省,但表现会很糟糕。要么显式地编写代码填充对象,要么考虑表达式树(尽管我相信在这种情况下表达式树过于复杂)
  • 如果这是来自数据库,请在存储过程中实现分页或select语句,以便只提取单个页面所需的数据
  • 如果出于某种原因需要一次填充所有内容,那么放弃分页逻辑,因为在上面的代码中没有使用它
  • 使用DataReader而不是DataTable。DataReader比DataTable/DataSet更快,开销更小
  • 使用列索引而不是列名来检索数据。使用列名与索引会导致额外的性能损失。如果需要动态执行此操作,则使用名称获取列的索引,存储它,然后使用存储的值

我想问,为什么一开始就要使用数据表来处理这么多行,但如果您坚持这样做,那么在将数据表转换为模型后,您始终可以删除数据表中的行。实际上,您在内存中保留了一组非常大的数据的两个副本。您是从数据库加载数据表还是动态构建数据表?@PaulAbbott对于如此大的数据集合,您建议使用什么?或者他们应该只考虑一次只获取少量数据,并以这种方式进行处理。如果数据来自数据库,为什么不直接通过数据读取器进行循环,这样成本更低?除非我遗漏了什么。@PaulAbbott,@WiseGod:实际上我正在将datatable填充到我使用反射的对象数据模型中。数据来自数据库,我只使用数据读取器加载数据。之后,我将使用反射将数据表填充到对象。感谢您的详细解释。让我更简要地解释一下我的问题。我有一个大型机数据库,使用ODBC从中导出50万条记录。现在我必须将数据表填充到数据模型(对象)中。数据模型或类有150多个属性,需要从datatable填充这些属性。我在每个数据行的每次迭代中都使用反射。请告诉我,除了反射之外,还有其他更好或更高效的方法可以这样做吗。(请注意,我有150多个属性需要填充)。我建议使用PropertyInfo.GetMethod,使用该MethodInfo创建委托,然后缓存每个属性的委托。您可以调用委托,而不是使用反射来获取值。这是一篇关于如何做到这一点的好文章:感谢您的回复,但您能否告诉我如何在这里使用委托/反射概念,特别是在将数据表填充到模型中时。一个小的代码片段或示例对我和其他查看此链接的用户都有很大的帮助。