Oracle
 sql >> Base de données >  >> RDS >> Oracle

Fuite de mémoire GetOracleDecimal

Il s'agit d'un ancien problème avec ODP.NET (voir ici :Problèmes de mémoire avec ODP .NET 10.1.0.4 ).

Le OracleDecimal type contient une référence à une instance d'une classe interne nommée OpoDecCtx . OpoDecCtx implémente IDisposable (car il fait lui-même référence à la mémoire non gérée), mais comme OracleDecimal n'implémente pas IDisposable, vous devrez attendre que le ramasse-miettes s'exécute pour libérer la mémoire non gérée sous-jacente. Vous pouvez vérifier tout cela à l'aide d'un outil tel que .NET Reflector.

Bien qu'il ne s'agisse pas techniquement d'une fuite de mémoire "physique" (la mémoire sera finalement libérée), c'est en fait un problème lorsque vous avez affaire à un grand nombre d'instances de type OracleDecimal. Je ne sais pas pourquoi Oracle n'implémente pas simplement IDisposable, c'est une chose simple à faire...

Quoi qu'il en soit, je vous suggère de faire un travail de piratage vous-même, en utilisant la réflexion :

public static class OracleExtentions
{
    public static void Dispose(this OracleDecimal od) // build an extension method
    {
        if (OracleDecimalOpoDecCtx == null)
        {
            // cache the data
            // get the underlying internal field info
            OracleDecimalOpoDecCtx = typeof(OracleDecimal).GetField("m_opoDecCtx", BindingFlags.Instance | BindingFlags.NonPublic);
        }
        IDisposable disposable = OracleDecimalOpoDecCtx.GetValue(od) as IDisposable;
        if (disposable != null)
        {
            disposable.Dispose();
        }
    }

    private static FieldInfo OracleDecimalOpoDecCtx;
}

Et vous l'utiliseriez comme ceci :

OracleDecimal od = reader.GetOracleDecimal(5);
decimal volume = (decimal)OracleDecimal.SetPrecision(od, 28);
od.Dispose();