2009-06-23 2 views
1

У меня есть клиентское приложение C#, вызывающее Windows webservice, написанное в вызове WCF. Процедура Sql и этот proc дают выход около 1,3 миллиона записей, тогда клиентское приложение C# хранит их в памяти и делает все проверки один за другим. . Я получаю ошибку :System.OutOfMemoryException

System.Exception: An exception has occurred when recalculating the balances, the transaction will be rolled back.


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, он работает нормально

ответ

4

Кажется, вы пытаетесь инициализировать общий список какого-либо типа, и при этом заканчивается память.

Сама процедура может быть успешной, но может также возвращать много, много строк.

Возможно, вы захотите выполнить свой код и проверить результаты запроса перед инициализацией объекта List.

Без дополнительной информации, боюсь, я не могу отладить больше.

Edit:

Вам нужно будет обрабатывать результаты хранимой процедуры в пакетах. Вы все равно можете использовать SqlDataReader, но я бы предложил создать список с максимальной емкостью чего-то относительно малого, например 1000, и прочитать из SqlDataReader до тех пор, пока вы не заполнили список ... затем очистите список и начните чтение заново:

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); 
    } 
} 
+0

Да, процесс дает результат, содержащий около 1,3 миллиона записей – rmdussa

+1

Вам нужно будет опубликовать эти записи! 1,3 миллиона - это LOT - и, как говорит среда исполнения .Net, у него закончилась нехватка памяти. –

0

также вы можете прочитать это article

“Out Of Memory” Does Not Refer to Physical Memory

1

вы также можете использовать класс MemoryFailPoint, чтобы проверить есть ли у вас достаточно памяти, прежде чем выделять большие массивы, списки или другие крупные объекты.

http://msdn.microsoft.com/en-us/library/system.runtime.memoryfailpoint.aspx

хороший блог о OutOfMemory

http://blogs.msdn.com/ericlippert/archive/2009/06/08/out-of-memory-does-not-refer-to-physical-memory.aspx

2

Просто вопрос - вы должны загрузить все 1,3 миллиона строк в памяти? Это много данных, даже если каждая строка говорит 1 КБ. Неудивительно, что ваше приложение изо всех сил пытается выполнить.

Возможно ли рефакторинг приложения для загрузки подмножества данных?

Смежные вопросы