我们正在使用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));
条件放在一起)
答案 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));