我有C#客户端应用程序调用在WCF中编写的Windows Web服务调用Sql Procedure并且此proc为输出提供大约130万条记录,然后C#客户端应用程序将它们保存在内存中并逐个进行所有验证 我收到了错误:
System.Exception:异常有 重新计算时发生的 余额,交易将 回滚。
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Collections.Generic.List`1.set_Capacity(Int32 value)
at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
at PitToPort.DataLayer.StockpileData.StockpileProfile.CreateStockpileProfileQualityFromAllPartialMovements()
at PitToPort.DataLayer.StockpileRecalc.Recalc.CreateSP_FOFO_FOLO_NegTransaction(Int32 modelID, StockpileProfile currentStockpileProfile, TransactionsRow drTransactions)
at PitToPort.DataLayer.StockpileRecalc.Recalc.CreateBalanceFOLO_FOFO_TWAA(TransactionsRow[] drTransactionsRows, Int32 modelID, StockpileProfileList stockpileProfileList)
at PitToPort.DataLayer.StockpileRecalc.Recalc.CreateBalances()
at QMastor.PitToPort.StockpileRecalculationBL.RecalcService.CreateBalances()
可能导致此错误以及如何纠正错误?我已经检查了proc,它运行正常
答案 0 :(得分:4)
您似乎正在尝试初始化某种类型的通用List,并且这样做会耗尽内存。
程序本身可能会成功,但也可能会返回许多行。
在初始化List对象之前,您可能需要单步执行代码并检查查询结果。
如果没有更多细节,我恐怕无法帮助调试更多。
编辑:
您需要批量处理存储过程的结果。您仍然可以使用SqlDataReader,但我建议创建一个最大容量相对较小的List,如1000,并从SqlDataReader读取,直到您填充List ...然后清除列表并再次开始读取:< / p>
SqlDataReader dr = cmd.ExecuteReader(); // where cmd is a SqlCommand
List<SomeType> items = new List<SomeType>(1000);
while(dr.Read()) {
// read the values for the row
SomeType obj = new SomeType(dr["id"], dr["value"], ...);
// add the object to the list
items.Add(obj);
// when the list is full, process it, and create a new one.
if(items.Count >= 1000) {
Process(items);
items = new List<SomeType>(1000);
}
}
答案 1 :(得分:2)
只是一个问题 - 您是否必须将所有130万行加载到内存中?即使每行说1KB,这也是很多数据。难怪您的应用程序难以执行。
是否可以重构您的应用程序以加载数据的子集?
答案 2 :(得分:1)
在分配大数组,列表或其他大对象之前,您还可以使用MemoryFailPoint类检查是否有足够的内存。
http://msdn.microsoft.com/en-us/library/system.runtime.memoryfailpoint.aspx
关于OutOfMemory的好博文
答案 3 :(得分:0)
您也可以阅读此article
“内存不足”不指物理内存