Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I convert an Enum to an Int for use in an Expression.Equals operation?

I am trying to dynamically build an expression tree in C#, which is compiled and used as the predicate for LINQ-to-SQL Where() call. The problem is that I am trying to compare an Enum (with int as its underlying type) directly against an Int, but this is failing with the error "The member MyEnumType has no supported translation to SQL".

Code:

ParameterExpression param = Expression.Parameter(typeof(MyClass), "obj"); //input parameter - this exposes a property of the Enum type
MemberExpression enumMember = Expression.Property(param, "MyEnumProperty"); //used to get the Enum typed property from the parameter

//MISSING STEP TO CAST THE ENUM OF THE MEMBER EXPRESSION TO AN INT?

BinaryExpression binaryExpr = Expression.Equal(enumMember, Expression.Constant(1));
LambdaExpression<Func<MyClass, bool>> whereClause = Expression.Lambda(binaryExpr, param);

//when whereClause is used to filter LINQ-to-SQL results, the error is thrown

I'm fairly new to expression trees and I can't figure this out. I have tried using

Expression.Convert(enumMember, typeof(int))

as the first part of the BinaryExpression but this doesn't fix it.

Any help is much appreciated.

like image 908
Lee D Avatar asked Sep 03 '10 11:09

Lee D


People also ask

Can enum be treated as int?

An Enum value cannot be treated as an int by default because then you would be able to provide any integer and there would be no compile time check to validate that the provided integer does in fact exist as a value in the Enumeration.

How do I convert an int to enum?

Convert int to Enum using Enum.Use the Enum. ToObject() method to convert integers to enum members, as shown below.

How to use enum parse?

Parse<TEnum>(String, Boolean)Converts the string representation of the name or numeric value of one or more enumerated constants specified by TEnum to an equivalent enumerated object. A parameter specifies whether the operation is case-insensitive.

Can we compare enum with int?

Cast Int To Enum may be of some help. Go with the 2nd option. The 1st one can cause an exception if the integer is out of the defined range in your Enumeration. In current example I compare to 'magic number' but in real application I am getting data from integer field from DB.


2 Answers

Simply, you shouldn't have to, as long as you've told LINQ-to-SQL about the enum (rather than mapping it as an int and having a separate property in C# that does the translation). For example, the following works fine:

var param = Expression.Parameter(typeof(DomainObject));
var body = Expression.Equal(Expression.Property(param, "SomeProperty"),
                         Expression.Constant(YourEnumType.SomeEnum));
var predicate = Expression.Lambda<Func<DomainObject, bool>>(body, param);
var count = db.Table.Where(predicate).Count();

The main point is that my SomeProperty property is mapped in the dbml to the enum. Simply overtype the type name with the enum type (including namespace).

Likewise, you shouldn't be giving it a 1, but rather the typed enum; for example:

Expression.Constant(Enum.ToObject(typeof(YourEnumType), 1))

(if all you know is 1)

like image 172
Marc Gravell Avatar answered Oct 12 '22 23:10

Marc Gravell


Thanks To Marc Gravell. (Expression Guru !) See Correct answer. I made a change to an Expression Routine to cater for this scenario. Normal properties or Enums. Incase someone finds this helpful

public static Expression<Func<TPoco, bool>> GetEqualsPredicate<TPoco>(string propertyName,
                                                                          object value)
                                                                          Type fieldType )
    {     

        var parameterExp = Expression.Parameter(typeof(TPoco), @"t");   //(tpoco t)
        var propertyExp = Expression.Property(parameterExp, propertyName);// (tpoco t) => t.Propertyname

        var someValue = fieldType.IsEnum // get and eXpressionConstant.  Careful Enums must be reduced
                     ? Expression.Constant(Enum.ToObject(fieldType, value)) // Marc Gravell fix
                     : Expression.Constant(value, fieldType);

        var equalsExp = Expression.Equal(propertyExp,  someValue); // yes this could 1 unreadble state if embedding someValue determination

        return Expression.Lambda<Func<TPoco, bool>>(equalsExp, parameterExp); 
    }
like image 28
phil soady Avatar answered Oct 13 '22 01:10

phil soady