2009-02-19 9 views
2

J'utilise ODP.Net version 11.1.0 pour insérer des données dans une base de données, et je constate une fuite de mémoire. Si je commente le code ci-dessous, il s'en va. Ce code est appelé des milliers de fois dans mon application, et je peux regarder le nombre d'octets dans tous les tas croître régulièrement pendant qu'il s'exécute. cmdStr contient une instruction d'insertion qui insère dans une table avec 375 colonnes. Les champs sont tous NUMBER à l'exception de deux - l'un est un DATE, et l'autre est un VARCHAR2 (20). Y a-t-il autre chose que je dois faire pour nettoyer OracleCommand? Aucune exception n'est levée ici - la commande insert est réussie à chaque fois.Fuite de mémoire avec OracleCommand

Editer: J'ai essayé de déplacer l'instruction return, et cela n'a eu aucun effet comme prévu - l'utilisation est vraiment un bloc try-finally. Mise à jour: J'ai utilisé CLRProfiler pour voir ce qui utilise la mémoire, et c'est un tas d'objets chaîne, ~ 2800 d'entre eux. Leurs références sont détenues par des objets HashTable appartenant à Oracle.DataAccess.Client.ConnDataPool. Pourquoi ODP.NET les conserve-t-il?

try 
{ 
    using (OracleCommand cmd = new OracleCommand(cmdStr, conn)) 
    { 
     cmd.CommandTimeout = txTimeout; 
     int nRowsAffected = cmd.ExecuteNonQuery(); 
     errMsg = null; 
     return EndpointResult.Success; 
    } 
} 
catch (OracleException e) 
{ 
    return BFOracleAdapter.HandleOracleException(e, out errMsg); 
} 
catch (Exception e) 
{ 
    errMsg = "OracleInsertOperation Exception: " + e.Message; 
    return EndpointResult.Error; 
} 
+0

Tout semble bien dans ce code. Questions: 1. Êtes-vous correctement disposé l'objet OracleConnection? 2. Qu'y a-t-il dans les chaînes que vous pouvez voir dans CLRProfiler? En tant que hack, je pense qu'il existe un moyen de fermer/réinitialiser toutes les connexions dans le pool de connexion ... – ConsultUtah

Répondre

0

Essayez de déplacer l'instruction return en dehors du bloc using.

+0

L'utilisation va nettoyer mais vous en sortez. Probablement le problème est le 'conn' n'étant pas disposé. – Loofer

1

Essayer la restructuration à quelque chose comme:

object o; 
    using (OracleCommand cmd = new OracleCommand(cmdStr, conn)) 
    { 
    try 
    { 
     cmd.CommandTimeout = txTimeout; 
     int nRowsAffected = cmd.ExecuteNonQuery(); 
     errMsg = null; 
     o = EndpointResult.Success; 
    } 
    catch (OracleException e) 
    { 
     o = BFOracleAdapter.HandleOracleException(e, out errMsg); 
    } 
    catch (Exception e) 
    { 
     errMsg = "OracleInsertOperation Exception: " + e.Message; 
     o = EndpointResult.Error; 
    } 
    finally 
    { 
     // clean up 
    } 
    } 
    return o 
1

Gardez-vous votre connexion ouverte? Essayez d'ouvrir une nouvelle connexion chaque fois que vous avez besoin d'exécuter cette commande (elle est regroupée de toute façon pour ne pas affecter les performances), fermez-la lorsque vous avez terminé la transaction et vérifiez si la fuite de mémoire disparaît.

4

Essayez d'envelopper une déclaration en utilisant le OracleConnection autour de votre déclaration en utilisant comme ceci:

Cela permettrait de se débarrasser de l'objet OracleConnection le plus tôt possible - même lorsqu'un OracleException serait occure dans les déclarations à l'aide .

0

Quel est le nombre maximal de connexions sur votre pool de connexions? Par défaut, le regroupement de connexions est activé avec 100 connexions max.

Vous ne montrez pas la partie du code qui crée/supprime les connexions. Je suppose que c'est plus probable où le problème va être trouvé. Essayez d'utiliser Oracle.ManagedDataAccess.Client à la place de Oracle.DataAccess.Client.