C# 大数据表始终引发System.outofmemory异常
我有一个大型数据表,其中包含大约500000行。我必须遍历该数据表,并在每一行上应用业务逻辑。 问题是,在对庞大的数据表进行一定程度的迭代之后,它会抛出System.OutofMemory异常 dt是包含500000条记录的数据表。 我尝试了以下方法: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
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更快,开销更小
- 使用列索引而不是列名来检索数据。使用列名与索引会导致额外的性能损失。如果需要动态执行此操作,则使用名称获取列的索引,存储它,然后使用存储的值