views:

122

answers:

4

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.

A: 

Try

(int) enumMember
Sjoerd
This doesn't compile: "Cannot convert type 'System.Linq.Expressions.MemberExpression' to 'int'"
Lee D
Heh, Sjoerd would be correct...if *enumMember* were an actual enum and not an expression tree abstraction of one.
Kirk Woll
A: 

look my friend first of all you have to modify your enum to be like that:

public enum myenum : int
{
item1 = 0,
item2 = 1
}

after that you can convert between int and that eunm by that way:

int x = (int) myenum.item1;
Ghiath Zarzar
A: 

I also think the issue is not related to the Enum but to the fact that the property is not mapped in LinqToSql (as you pointed out in your comment). This page seems to describe exactly the issue you are running into. You can project into this property but not filter on it.

What you could do is force Linq to Object to handle that part by inserting a call to ToList() (or similar) before this filter.

Johann Blais
+1  A: 

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)

Marc Gravell