Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

GetOracleDecimal Memory Leak


Este é um problema antigo com o ODP.NET (veja aqui:Problemas de memória com ODP .NET 10.1.0.4 ).

O OracleDecimal type contém uma referência a uma instância de uma classe interna chamada OpoDecCtx . OpoDecCtx implementa IDisposable (como ele próprio faz referência à memória não gerenciada), mas como o OracleDecimal não implementa IDisposable, você terá que esperar que o coletor de lixo seja executado para liberar a memória não gerenciada subjacente. Você pode verificar tudo isso usando uma ferramenta como o .NET Reflector.

Embora não seja tecnicamente um vazamento de memória "física" (a memória será eventualmente liberada), na verdade é um problema quando você está lidando com uma grande quantidade de instâncias do tipo OracleDecimal. Não sei porque a Oracle não implementa simplesmente IDisposable, é uma coisa simples de fazer...

De qualquer forma, sugiro que você faça algum trabalho de hack, usando reflexão:
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;
}

E você usaria assim:
OracleDecimal od = reader.GetOracleDecimal(5);
decimal volume = (decimal)OracleDecimal.SetPrecision(od, 28);
od.Dispose();