2009-06-23 10 views
1

J'ai une application client C# Windows Webservice écrite en WCF appelant Sql Procédure et ce proc donne une sortie autour de 1,3 million d'enregistrements alors l'application client C# les garde en mémoire et fait toutes les validations une par une :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() 

ce qui pourrait être à l'origine de cette erreur et comment y remédier? J'ai vérifié dans proc, il fonctionne bien

Répondre

4

Il semble que vous essayez d'initialiser une liste générique d'un certain type, et ce faisant, à court de mémoire.

La procédure en elle-même peut réussir, mais peut également renvoyer beaucoup, beaucoup de lignes.

Vous souhaiterez peut-être parcourir votre code et inspecter les résultats de la requête avant d'initialiser l'objet List.

Sans plus de détails, je crains de ne pouvoir plus déboguer.

Edit:

Vous devrez gérer les résultats de la procédure stockée par lots. Vous pouvez toujours utiliser un SqlDataReader, mais je suggère de faire une liste avec une capacité maximale de quelque chose de relativement petit, comme 1000, et lire depuis SqlDataReader jusqu'à ce que vous ayez rempli la liste ... puis effacez la liste et recommencez la lecture:

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

Oui, le proc donne un résultat d'environ 1,3 million d'enregistrements – rmdussa

+1

Vous allez avoir besoin de paginer ces enregistrements! 1,3 million est BEAUCOUP - et bien, comme le dit l'exécution de .Net - il manque de mémoire. –

0

aussi, vous pouvez lire ce article

“Out Of Memory” Does Not Refer to Physical Memory

2

Juste une question - avez-vous de charger tous les 1,3 million de lignes en mémoire? C'est beaucoup de données, même si chaque ligne est dit 1KB. Pas étonnant que votre application ait du mal à s'exécuter.

Est-il possible de refactoriser votre application pour charger un sous-ensemble de données?