Une Exception de type 'System.OutOfMemoryException " a été levée. C# lors de l'utilisation de IDataReader
J'ai une application dans laquelle je dois obtenir une grande quantité de données à partir de DB.
Car elle n'est pas d'obtenir toutes ces lignes (c'est près de 2 000 000 de lignes...), je l'ai découpé dans des pauses, et je lance à chaque fois que la requête sql et obtenir seulement 200 000 lignes à chaque fois.
- Je utiliser DataTable à qui je entrer toutes les données (sens - tous les 2 000 000 de lignes devrait être là).
Les quelques premières pistes sont très bien. Puis il échoue avec l'exception OutOfMemoryException.
Mon code fonctionne comme suit:
private static void RunQueryAndAddToDT(string sql, string lastRowID, SqlConnection conn, DataTable dt, int prevRowCount)
{
if (string.IsNullOrEmpty(sql))
{
sql = generateSqlQuery(lastRowID);
}
if (conn.State == ConnectionState.Closed)
{
conn.Open();
}
using (IDbCommand cmd2 = conn.CreateCommand())
{
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = sql;
cmd2.CommandTimeout = 0;
using (IDataReader reader = cmd2.ExecuteReader())
{
while (reader.Read())
{
DataRow row = dt.NewRow();
row["RowID"] = reader["RowID"].ToString();
row["MyCol"] = reader["MyCol"].ToString();
... //In one of these rows it returns the exception.
dt.Rows.Add(row);
}
}
}
if (conn != null)
{
conn.Close();
}
if (dt.Rows.Count > prevRowCount)
{
lastRowID = dt.Rows[dt.Rows.Count - 1]["RowID"].ToString();
sql = string.Empty;
RunQueryAndAddToDT(sql, lastRowID, conn, dt, dt.Rows.Count);
}
}
Il me semble que si le lecteur garde la collecte de lignes, et c'est pourquoi Il déclenche une exception seulement dans la deuxième ou troisième ronde.
Ne pas le nettoyer à l'Aide de la mémoire de son fait?
Ce qui peut résoudre mon problème?
Note: je dois expliquer - je n'ai pas d'autre choix que d'obtenir toutes ces lignes à la datatable, Depuis que j'ai quelques manipulations plus tard, et l'ordre des lignes est important, et je ne peux pas diviser parce que parfois, je dois prendre les données de certaines lignes et le mettre en une seule ligne et ainsi de suite et ainsi de suite, donc je ne peux pas l'abandonner.
Grâce.
Chargement de 2M lignes est assez rare - la plupart du temps, l'idée est de minimiser la quantité de données chargées. Et si vous avez besoin de 2M lignes, DataTable peut-être pas le meilleur modèle de toute façon (DataTable a la verticale). J'avais de le charger dans un POCO modèle, personnellement.
OriginalL'auteur DA_Prog | 2012-12-24
Vous devez vous connecter pour publier un commentaire.
Vérifier que vous êtes la construction d'un processus 64 bits et non 32 bits, qui est par défaut le mode de compilation de Visual Studio. Pour ce faire, cliquez droit sur votre projet, Propriétés -> Build -> plate-forme cible : x64. Comme tout processus 32 bits, les applications de Visual Studio compilé en 32 bits ont une limite de mémoire virtuelle de 2 go.
Processus 64 bits n'ont pas cette limitation, car ils utilisent des pointeurs 64-bit, de sorte que leur maximum théorique de l'espace d'adressage de 16 exaoctets (2^64). En réalité, Windows x64 limites de la mémoire virtuelle du processus à 8 to. La solution à la limite de la mémoire problème est alors de compiler en 64 bits.
Cependant, la taille de l'objet dans Visual Studio est toujours limité à 2 go par défaut. Vous serez en mesure de créer plusieurs tableaux dont la taille combinée sera supérieure à 2 GO, mais vous ne pouvez pas, par défaut, créer des tableaux plus grand que 2 GO. Heureusement, si vous voulez continuer à créer des tableaux plus grand que 2 GO, vous pouvez le faire en ajoutant le code suivant à votre application.fichier de configuration:
A fonctionné pour moi! Merci!
Je vous remercie. A fonctionné pour moi
Je suis à l'aide de l'application 32 bits et je suis en train d'ajouter 1700000 des enregistrements dans la table de Données à partir de sql lecteur de sa levée de l'exception de mémoire insuffisante. Après l'utilisation de la solution mentionnée ci-dessus encore, il a jeté la même erreur. Merci de me suggérer pour résoudre son problème.
OriginalL'auteur Shift Technology
Je pense que tout simplement vous manquez de mémoire, parce que votre DataTable est tellement grande de toutes les lignes que vous continuez à ajouter.
Vous souhaiterez peut-être essayer un modèle différent dans ce cas.
Au lieu de mise en mémoire tampon des lignes dans une liste (ou un DataTable), pouvez-vous simplement de rendement les lignes qu'ils sont disponibles pour l'usage quand ils arrivent?
OriginalL'auteur Andrew
Puisque vous êtes à l'aide d'un
DataTable
, permettez-moi de partager un problème aléatoire que j'ai eu l'aide de l'un. Vérifiez votre Construire des propriétés. J'ai eu un problème avec un DataTable jeter un souvenir d'exception au hasard. Comme il s'est avéré, le projet de créer une Plate-forme cible a été fixé àPrefer 32-bit
. Une fois que j'non sélectionné cette option, le hasard de la mémoire exception s'en alla.OriginalL'auteur Carlos A Merighe
Vous stockez une copie des données à
dt
. Vous êtes tout simplement de stocker autant que la machine est en cours d'exécution hors de la mémoire. Donc, vous avez quelques options:Pour augmenter la mémoire disponible, vous pouvez ajouter de la mémoire physique de la machine. Notez qu'un .NET processus sur une machine 32 bits ne sera pas en mesure d'accéder à plus de 2 go de mémoire (3 GO si vous activez le commutateur 3 gb dans
boot.ini
) de sorte que vous pouvez avoir besoin pour passer en 64 bits (la machine et du processus) si vous souhaitez adresser plus de mémoire que cela.De la récupération de moins de données est probablement la voie à suivre. En fonction de ce que vous essayez d'atteindre, vous pourriez être en mesure d'effectuer la tâche sur des sous-ensembles de données (peut-être même sur des lignes individuelles). Si vous effectuez une sorte d'agrégation (par exemple, un produire un rapport ou un résumé à partir des données), vous pourriez être en mesure d'employer Réduire La Carte.
bon point, mais il rend la mémoire, le lecteur est à l'aide admissible de la collection, qui empêcherait la OOM dans ce cas, si les résultats n'étaient pas stockées ailleurs.
Non, parce que le lecteur n'a pas de tenir toutes les données: c'est une API de diffusion en continu.
Ah Ah, merci pour la clarification. Je vais modifier la réponse.
OriginalL'auteur Paul Ruane