EF Core 2.2升级至3.1后LINQ查询触发InvalidOperationException异常
解决EF Core 3.1升级后的导航属性查询报错问题
嗨,我来帮你搞定这个升级后遇到的EF Core问题!这个报错本质是EF Core 3.1的查询翻译逻辑和2.2有很大差异导致的,咱们一步步拆解:
为什么会报错?
EF Core 2.2会偷偷把一些无法翻译的查询逻辑放到客户端处理,但3.1开始取消了大部分自动客户端评估,而且对导航属性的嵌套过滤查询处理更严格。你的代码里在Select中直接对导航属性ActualLocalizationTranslation应用Where(translationConditionExpression),这种嵌套的表达式过滤让EF Core无法正确生成对应的SQL,所以抛出了那个关于NavigationExpandingExpressionVisitor的错误。
怎么修改代码?
这里有几个可行的解决方案,你可以根据自己的场景选择:
方案1:用过滤式Include加载导航属性
EF Core 3.0及以上支持对Include的导航属性直接加过滤条件,这样EF能更好地理解你的查询意图,生成正确的SQL:
var resource = locResRepo.GetWhere(i => i.ForApplication.ToLower() == applicationName.ToLower()) .Where(resourcesConditionExpression) // 先过滤导航属性再加载 .Include(l => l.ActualLocalizationTranslation.Where(translationConditionExpression)) .Select(item => new ResourceKeyObject { Id = item.Id, ResourceKey = item.ResourceKey, ResourceKeyValues = item.ActualLocalizationTranslation .Select(v => new ResourceKeyValues { Language = v.Language, KeyValue = v.Value }).ToList() }).ToList();
方案2:改用Join关联查询
如果过滤式Include不适用你的场景,你可以把主实体和导航属性用Join显式关联,再分组处理,这样EF的查询翻译器更容易处理:
// 假设dbContext是你的数据库上下文实例 var resource = locResRepo.GetWhere(i => i.ForApplication.ToLower() == applicationName.ToLower()) .Where(resourcesConditionExpression) .Join( dbContext.ActualLocalizationTranslation.Where(translationConditionExpression), res => res.Id, trans => trans.ResourceId, (res, trans) => new { res, trans } ) .GroupBy(x => x.res) .Select(g => new ResourceKeyObject { Id = g.Key.Id, ResourceKey = g.Key.ResourceKey, ResourceKeyValues = g.Select(v => new ResourceKeyValues { Language = v.trans.Language, KeyValue = v.trans.Value }).ToList() }).ToList();
额外注意点
- 确保你的
GetWhere方法返回的是IQueryable<LocalizationResources>而不是IEnumerable,如果是IEnumerable的话会提前触发客户端评估,后续的查询就无法被EF翻译了。 - 如果
translationConditionExpression是复杂的自定义表达式,你可以尝试把它拆成EF能识别的简单条件,或者用Expression的组合方法确保它能被正确翻译。
内容的提问来源于stack exchange,提问作者Qhori
相关产品推荐
相关产品推荐

