Oracle
 sql >> Datenbank >  >> RDS >> Oracle

GetOracleDecimal Speicherleck

Dies ist ein altes Problem mit ODP.NET (siehe hier:Speicherprobleme mit ODP .NET 10.1.0.4 ).

Das OracleDecimal type enthält eine Referenz auf eine Instanz einer internen Klasse namens OpoDecCtx . OpoDecCtx implementiert IDisposable (da es selbst auf nicht verwalteten Speicher verweist), aber da OracleDecimal IDisposable nicht implementiert, müssen Sie warten, bis der Garbage Collector ausgeführt wird, um den zugrunde liegenden nicht verwalteten Speicher freizugeben. Sie können dies alles mit einem Tool wie .NET Reflector überprüfen.

Obwohl es sich technisch gesehen nicht um ein "physisches" Speicherleck handelt (Speicher wird schließlich freigegeben), ist es tatsächlich ein Problem, wenn Sie es mit einer großen Anzahl von Instanzen des Typs OracleDecimal zu tun haben. Ich weiß nicht, warum Oracle IDisposable nicht einfach implementiert, es ist eine einfache Sache ...

Wie auch immer, ich schlage vor, dass Sie selbst einen Hack-Job machen, indem Sie Reflektion verwenden:

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;
}

Und Sie würden es so verwenden:

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