通过System.Linq.Expressions.Expression创建表达式时,LINQ to Entities无法识别方法'Boolean HasFlag(System.Enum)'

时间:2017-09-27 14:09:56

标签: c# entity-framework linq enums

我们正在使用System.Linq.Expressions.Expression来构建自定义表达式,这些表达式应用于.Where()的{​​{1}}。

我想要实现的是,将IQueryable方法(introduced in EF 6.1)应用于属性,然后在.HasFlag()表达式中使用。

我有以下代码:

.Where()

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))); 的值显示为propertyExpression,而{x.Type}显示为hasFlagMethod,这对我来说都很合适。

{Boolean HasFlag(System.Enum)}的值是hasFlagExpression,除{x.Type.HasFlag(Convert(Foo))}部分外,对我来说看起来也完全没问题,但这样做是必要的,否则我会得到另一个例外,即它抱怨参数不能应用于此方法,因为它不是Convert(Foo)

当我们使用此System.Enum枚举IQueryable时,我们会遇到以下异常:

.Where()

直接在NotSupportedException: LINQ to Entities does not recognize the method 'Boolean HasFlag(System.Enum)' method, and this method cannot be translated into a store expression. 上调用它(我们也使用EF 6.1,它增加了对IQueryable的支持),如

Enum.HasFlag()

但是这样称它不是一个选项,因为它需要对我们所有的实体都是通用的。 (我们根据数据表中的过滤列将这些Entities.Where(x => x.Type.HasFlag(BarEnum.Foo)); 条件放在一起)

1 个答案:

答案 0 :(得分:5)

代码中的HasFlag方法的MethodInfo与编译器生成的方法之间存在一个不太明显的差异。前一种情况下的ReflectedType属性为typeof(YourEnum),而后者为typeof(Enum)。两种情况下的DeclaringType属性都是同一个 - typeof(Enum),因此调试显示,但这足以打破EF查询转换器。

要解决此问题,只需更改

即可
var hasFlagMethod = targetType.GetMethod(nameof(Enum.HasFlag));

var hasFlagMethod = typeof(Enum).GetMethod(nameof(Enum.HasFlag));