Skip to content

Enums: error when dbValue doesn't exist in Enum-Values #1099

@Garios

Description

@Garios

Bug Description

I think #956 has the same problem.

If I have values in table, which doesn't exist in the given Enum, then I get the following error. I don't use string-values. I use byte, short, int, long.

Exception Message:

System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name'

Model:

    public enum TestEnum : int
    {
        None = 0,
        Type1 = 1
    }
    public class TestTable
    {
        public long ID { get; set; }
        public TestEnum TestType { get; set; }
    }

Compiler creates:

new TestTable() 
{
    ID = reader.GetInt64(0),
    TestEnum = Convert(Parse(TestEnum, GetName(TestEnum, Convert(reader.GetInt32(1), Object)), True), TestEnum)
}

Assume reader.GetInt32(1) returns "4". But "4" doesn't exist in TestEnum. Then GetName returns "null". Parse throws the error...

Expected Behaviour
return default(TestEnum)

Possible Solution

long dbValue = 4; //note, in this case the db-type differs from the corresponding enum-type int
var baseType = typeof(TestEnum).GetEnumUnderlyingType();

object convertedDbValue = dbValue;
if (baseType != dbValue.GetType()) //if dbValue-Type differs from underlying enum-type
	convertedDbValue = Convert.ChangeType(dbValue, baseType); //ex. long to int

object result;
if (Enum.IsDefined(typeof(TestEnum), convertedDbValue))
	result = Enum.ToObject(typeof(TestEnum), dbValue);
else
	result = default(TestEnum);
return result;

Solution translated to Compiler
Replace the following Method in Compiler.cs:

(I never used Expression before!)

internal static Expression ConvertExpressionToEnumExpressionForNonString(Expression expression, Type toEnumType)
{
	Type baseType = toEnumType.GetEnumUnderlyingType();
	if (baseType != expression.Type)
	{
		var convertMethod = StaticType.Convert.GetMethod("ChangeType", new[] { StaticType.Object, StaticType.Type });
		var convertParameters = new Expression[]
		{
			Expression.Convert(expression, StaticType.Object),
			Expression.Constant(baseType)
		};
		expression = Expression.Call(convertMethod, convertParameters);
	}
	else
		expression = Expression.Convert(expression, StaticType.Object);

	var isDefinedMethod = StaticType.Enum.GetMethod("IsDefined", new[] { StaticType.Type, StaticType.Object });
	var isDefinedParameters = new Expression[]
	{
			Expression.Constant(toEnumType),
			expression
	};            
	var isDefinedExpression = Expression.Call(isDefinedMethod, isDefinedParameters);

	var toObjectMethod = StaticType.Enum.GetMethod("ToObject", new[] { StaticType.Type, StaticType.Object });
	var toObjectParameters = new Expression[]
	{
			Expression.Constant(toEnumType),
			expression
	};
	var toObjectExpression = Expression.Call(toObjectMethod, toObjectParameters);

	var defaultExpression = Expression.Convert(Expression.Default(toEnumType), StaticType.Object);

	return Expression.Condition(isDefinedExpression, toObjectExpression, defaultExpression);
}

Library Version:
Current master.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingfixedThe bug, issue, incident has been fixed.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions