Search code examples
c#oracle-databaseentity-frameworkexceptionoracle-manageddataaccess

Strange Behavior (Bug) of Oracle Data Provider (InvalidCastException: Specified Cast is not Valid)


Oracle ManagedDataAccess seems to have an issue, if you try to execute the following example, you might have an error (it's unexpected; changing to other field yet same datatype might result no issue); though the entity framework has materialized the query with no issue:

INVENTORY
.GroupBy(inv => 1)
.Select(invGroup => new 
{
    GrossWeight = invGroup.Sum(inv => inv.GROSS_WEIGHT / inv.BASE_QTY_PER_UNIT)
})

the previous code will cause the follow exception:

   InvalidCastException
   Specified cast is not valid. 
   StackTrace
   at Oracle.ManagedDataAccess.Client.OracleDataReader.GetDecimal(Int32 i)
   at Oracle.ManagedDataAccess.Client.OracleDataReader.GetValue(Int32 i)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.ErrorHandlingValueReader`1.GetValue(DbDataReader reader, Int32 ordinal)
   at lambda_method(Closure , Shaper )
   at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
   at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
   at UserQuery

Searching on the Net, seems other people have got this exception https://chrismay.org/2015/07/30/bug-in-oracledatareader-causing-invalidcastexception/


Solution

  • There are two ways of workarounds:

    Option#1 Casting the desired value into float

    INVENTORY
    .GroupBy(inv => 1)
    .Select(invGroup => new 
    {
        GrossWeight = invGroup.Sum(inv => (float)inv.GROSS_WEIGHT / (float)inv.BASE_QTY_PER_UNIT)
    })
    

    Option#2 Performing the summation in memory, by using AsEnumerable() as follow

    INVENTORY
    .GroupBy(inv => inv.BASE_QTY_PER_UNIT)
    .Select(invGroup => new 
    {
        GrossWeight = invGroup.Sum(inv => inv.GROSS_WEIGHT),
        BaseQuantityPerUnit = invGroup.Key
    })
    .AsEnumerable()
    .Select(anony => new
    {
        GrossWeight = anony.GrossWeight / anony.BaseQuantityPerUnit
    })