We are using System.Linq.Expressions.Expression
to build custom expressions which are applied on the .Where()
of our IQueryable
.
What I want to achieve is, to apply the .HasFlag()
method (introduced in EF 6.1) on the property which is then used in the .Where()
expression.
I have following code:
var memberExpression = propertyExpression as MemberExpression;
var targetType = memberExpression?.Type ?? typeof(decimal?);
var value = Enum.Parse(type, searchValue);
var hasFlagMethod = targetType.GetMethod(nameof(Enum.HasFlag));
var hasFlagExpression = Expression.Call(propertyExpression, hasFlagMethod, Expression.Convert(Expression.Constant(value), typeof(Enum)));
The value of propertyExpression
is being displayed as {x.Type}
and the hasFlagMethod
is being shown as {Boolean HasFlag(System.Enum)}
which both look fine to me.
The value of hasFlagExpression
is {x.Type.HasFlag(Convert(Foo))}
which also looks completely fine to me except the Convert(Foo)
part but doing this was necessary otherwhise I would get another Exception that it is complaining that the parameter cannot be applied to this method as it is not System.Enum
.
And at the time we enumerate the IQueryable
with this .Where()
we get following exception:
NotSupportedException: LINQ to Entities does not recognize the method
'Boolean HasFlag(System.Enum)' method, and this method cannot
be translated into a store expression.
Calling it directly on the IQueryable
works though (we are also using EF 6.1 which added support for Enum.HasFlag()
) as in
Entities.Where(x => x.Type.HasFlag(BarEnum.Foo));
But calling it like this is not an option as it needs to be generic for all our entities. (We put those .Where()
conditions together according to the filtered columns in our Datatables)
There is a small not easily visible difference between the MethodInfo
of the HasFlag
method in your code and the one generated by the compiler. The ReflectedType
property in the former case is typeof(YourEnum)
while in the later - typeof(Enum)
. The DeclaringType
property in both cases is one and the same - typeof(Enum)
, hence the debug display, but that's enough to break the EF query translator.
To fix the issue, simply change
var hasFlagMethod = targetType.GetMethod(nameof(Enum.HasFlag));
to
var hasFlagMethod = typeof(Enum).GetMethod(nameof(Enum.HasFlag));
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With