EF Core 6中ExpressionVisitor Lambda Compile报reducible node错误
EF Core 3升级至EF Core 6(PostgreSQL)运行报
must be reducible node错误解决 问题定位
该错误和自定义的CaseInsensitiveAccentSensitiveExpressionVisitor逻辑无关——即使访问器仅调用基类实现无自定义逻辑,错误仍会触发,根因出在原代码中对查询表达式的处理逻辑:
queryable = (IQueryable)Expression.Lambda(visitExpression).Compile().DynamicInvoke();
EF Core 6对内部查询表达式树做了重构,新增了QueryRootExpression等EF Core专属的查询节点,这类节点不属于标准可编译CLR表达式,不支持直接包装为普通Lambda进行编译执行。EF Core 3版本的表达式树全由标准CLR表达式节点构成,因此这套写法可以正常运行,升级后就会抛出节点不可约简的错误。
修复方法
移除将表达式包装为Lambda编译、动态调用的逻辑,直接通过IQueryable对应的查询提供器,基于修改后的表达式生成新的查询对象即可,修复后的ApplyFilter方法代码如下:
private IQueryable<T> ApplyFilter(IQueryable<T> query, string rawFilter, ODataQueryOptionParser oDataQueryOptionParser, ODataQueryContext oDataQueryContext) { FilterQueryOption filter = new FilterQueryOption(rawFilter, oDataQueryContext, oDataQueryOptionParser); var queryable = filter.ApplyTo(query, new ODataQuerySettings()); var visitor = new CaseInsensitiveAccentSensitiveExpressionVisitor(); var queryExpression = queryable.Expression; var visitExpression = visitor.Visit(queryExpression); // 替换原有的编译动态调用逻辑 queryable = queryable.Provider.CreateQuery(visitExpression); return (IQueryable<T>)queryable; }
后续实现自定义访问器的注意事项
CaseInsensitiveAccentSensitiveExpressionVisitor用于给字符串字段追加ToLower实现大小写不敏感筛选时,仅对实体类型的字符串属性成员访问节点追加ToLower()调用即可,不要对常量、参数中的字符串值做相同处理,避免生成无效SQL或触发转换错误。
内容的提问来源于stack exchange,提问作者JudgeProphet
相关产品推荐
相关产品推荐

