升级Microsoft.EntityFrameworkCore.SqlServer至2.1.1版本时遇代码错误求助
解决EF Core 2.1.1升级后内部查询编译API反射报错问题
升级Microsoft.EntityFrameworkCore.SqlServer至2.1.1版本后,原有通过反射访问EF Core内部查询编译相关API的代码出现错误,涉及IQueryModelGenerator、RelationalQueryModelVisitor和CreateQueryModelVisitor三个核心部分。
错误原因
EF Core 2.1对查询编译模块的内部架构进行了重构,大量非公共API的成员名称、类型定义或访问方式发生了变更,导致原有反射代码无法找到目标成员。
解决方案
方案一:避免依赖内部API(推荐)
EF Core的非公共API不提供向后兼容性承诺,版本升级极易引发此类问题。建议改用官方公开API或稳定的第三方工具实现需求:
- 若需获取查询SQL语句:可通过EF Core日志系统拦截(配置日志级别为
Information,过滤Microsoft.EntityFrameworkCore.Database.Command类别日志),或使用适配EF Core 2.x的第三方库如EFCore.SqlQuery。 - 若需自定义查询逻辑:优先使用官方提供的
IQueryable扩展、查询过滤器或自定义表达式访问器。
方案二:调整反射代码适配2.1.1
若必须依赖内部API,可按以下方式修改反射逻辑(注意:内部API仍可能随版本变更,需自行验证):
using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Query.Internal; using System.Reflection; // 假设queryable为目标IQueryable<TEntity>实例 var queryProvider = (IQueryProvider)queryable.Provider; // 获取QueryCompiler var queryCompilerField = queryProvider.GetType().GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance); var queryCompiler = queryCompilerField.GetValue(queryProvider); // 获取QueryCompilationContextFactory var contextFactoryProp = queryCompiler.GetType().GetProperty("QueryCompilationContextFactory", BindingFlags.Public | BindingFlags.Instance); var queryCompilationContextFactory = (IQueryCompilationContextFactory)contextFactoryProp.GetValue(queryCompiler); var queryCompilationContext = queryCompilationContextFactory.Create(false); // 获取QueryModelGenerator var modelGeneratorProp = queryCompilationContextFactory.GetType().GetProperty("QueryModelGenerator", BindingFlags.NonPublic | BindingFlags.Instance); var queryModelGenerator = (IQueryModelGenerator)modelGeneratorProp.GetValue(queryCompilationContextFactory); var queryModel = queryModelGenerator.ParseQuery(queryable.Expression); // 创建RelationalQueryModelVisitor var createVisitorMethod = queryCompilationContext.GetType().GetMethod("CreateQueryModelVisitor", BindingFlags.Public | BindingFlags.Instance); var modelVisitor = (RelationalQueryModelVisitor)createVisitorMethod.Invoke(queryCompilationContext, new object[] { queryCompilationContext.QueryTrackingBehavior }); // 生成查询执行器 var executor = modelVisitor.CreateQueryExecutor<TEntity>(queryModel);
内容的提问来源于stack exchange,提问作者kinjal
相关产品推荐
相关产品推荐

