Forum:  Bugs & Issues

Thread:  ArgumentException returning enum in Oracle


TomDog (User)   Posted on: 26-Feb-2019 10:43:14.
This works fine in SQl server
Code:
from p__0 in Finding
select new
{
    Overdue = p__0.FindingID == p__0.FindingID
                    ? AQD.Helpers.OverdueType.Overdue
                            : AQD.Helpers.OverdueType.None
}
but in Oracle it gives
Code:
The value passed in must be an enum base or an underlying type for an enum, such as an Int32.Parameter name: value

at System.Enum.ToObject(Type enumType, Object value)
at lambda_method(Closure , ProjectionRow , Int32[] )
at SD.LLBLGen.Pro.LinqSupportClasses.DataProjectorToObjectList`1.<>c__DisplayClass4_0.<.ctor>b__0(Object[] r, Int32[] i)
at SD.LLBLGen.Pro.LinqSupportClasses.DataProjectorToObjectList`1.AddRowToResults(Object[] rawProjectionResult)
at SD.LLBLGen.Pro.ORMSupportClasses.ProjectionUtils.FetchProjectionFromReader(List`1 valueProjectors, IGeneralDataProjector projector, IDataReader dataSource, Int32 rowsToSkip, Int32 rowsToTake, Boolean clientSideLimitation, Boolean clientSideDistinctFiltering, Boolean clientSidePaging, Boolean performValueProjectionsOnRawRow, Boolean postProcessDBNullValues, Dictionary`2 typeConvertersToRun, IRetrievalQuery queryExecuted)
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchProjection(List`1 valueProjectors, IGeneralDataProjector projector, IRetrievalQuery queryToExecute, Boolean performValueProjectionsOnRawRow, Boolean postProcessDBNullValues, Dictionary`2 typeConvertersToRun)
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchProjection(List`1 valueProjectors, IGeneralDataProjector projector, QueryParameters parameters)
at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.<>c__DisplayClass22_0.<FetchProjection>b__0()
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteValueListProjection(QueryExpression toExecute)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression, Type typeForPostProcessing)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression)
at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.System.Collections.IEnumerable.GetEnumerator()
Workaround is to do
Code:
from p__0 in Finding
select new
{
    Overdue = (AQD.Helpers.OverdueType)(p__0.FindingID == p__0.FindingID
                    ? (int)AQD.Helpers.OverdueType.Overdue
                            : (int)AQD.Helpers.OverdueType.None)
}

SQL is
Code:
SELECT CASE WHEN CASE WHEN ( "LPLA_1"."FINDING_ID" = "LPLA_1"."FINDING_ID") THEN 1 ELSE 0 END=1 THEN 3 ELSE 0 END AS "Overdue"
FROM
"AQD"."QAOC_FINDING" "LPLA_1"
Enum is
Code:
    public enum OverdueType
    {
        //Due in 15+ days
        [Display(ResourceType = typeof(RiskLabels), Name="Label_Overdue_None")]
        None = 0,
        //Due in 8-14 days
        [Display(ResourceType = typeof(RiskLabels), Name="Label_Overdue_WarnOne")]
        DueInTwoWeeks = 1,
        //Due within 7 days
        [Display(ResourceType = typeof(RiskLabels), Name="Label_Overdue_WarnTwo")]
        DueInOneWeek = 2,
        [Display(ResourceType = typeof(RiskLabels), Name="Label_Overdue_Overdue")]
        Overdue = 3,
    }


version="5.5.2-hotfix-20190225"
Otis (LLBLGen Pro Team)   Posted on: 26-Feb-2019 16:19:42.
The SQL you post, is that before or after the 'workaround'? The only reason I can think of that it might fail is that the values in the case statement return as System.Decimal from the oracle datareader... Dissapointed

Not sure how to even fix this. A type conversion before the enum conversion could work but it's irrelevant for all situations except this one. A convert in the query could help too but it's not really possible to include that at the level where the query is determined as it doesn't know it has to emit that convert.

I'll check if I can see if the values are decimals.


Otis (LLBLGen Pro Team)   Posted on: 26-Feb-2019 16:44:45.
yep, the values are decimals
Code:

var metaData = new LinqMetaData(adapter);
var q = from e in metaData.Emp
        select new
             {
                 Val = e.Empno == e.Empno ? TestEnum.Equal : TestEnum.Unequal
             };
var results = q.ToList();

Gives one value, a 1, and orm profiler's resultset fetch's schema says the column is a System.Decimal.

We've to look into how to fix this, it doesn't look like there's an easy fix here....
Otis (LLBLGen Pro Team)   Posted on: 27-Feb-2019 12:48:28.
It's very odd tho.

Code:

SELECT CASE
         WHEN CASE
                WHEN ("LPLA_1"."EMPNO" = "LPLA_1"."EMPNO") THEN 1
                ELSE 0
             END = 1 THEN :p2
         ELSE :p4
     END AS "Val"
FROM "SCOTT"."EMP" "LPLA_1"

is the SQL. p2 and p4 are both Int32. Still the result value is Decimal, not Int32. Confused

Tho I think I can solve this in the enum converter itself. First check if the type is in a list of acceptable types. If not, try a Convert.ChangeType() to int. If that works, use that, if not, use as-is and let Enum.ToObject throw.


Otis (LLBLGen Pro Team)   Posted on: 27-Feb-2019 13:26:07.
Managed to fix this with the change in the previous post Regular Smiley

Test now succeeds properly and all other tests work too.

Code:

[Test]
public void ConvertValuesInProjectionToEnums()
{
    using(var adapter = new DataAccessAdapter())
    {
        var metaData = new LinqMetaData(adapter);
        var q = from e in metaData.Emp
                select new
                     {
                         Val = e.Empno == e.Empno ? TestEnum.Equal : TestEnum.Unequal
                     };
        var results = q.ToList();
        Assert.IsTrue(results.Count > 0);
        Assert.AreEqual(TestEnum.Equal, results[0].Val);
    }
}


Fixed in next build.

Waiting for the UoW issue
Otis (LLBLGen Pro Team)   Posted on: 27-Feb-2019 16:55:20.
Hotfix is now available

TomDog (User)   Posted on: 28-Feb-2019 11:40:08.
Yep sorted - thanksLaugh