You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF6迁移至EF Core 3.1.26时查询抛出KeyNotFoundException问题

问题:EF 6迁移至EF Core 3.1.26时查询抛出KeyNotFoundException

正在将.NET Framework应用从EF 6迁移到EF Core 3.1.26,执行以下查询时抛出KeyNotFoundException:

var data = context.Applications
    .Select(a => new
    {
        a.Id,
        Attempt = a.Attempts
            .Select(fa => new
            {
                fa.CandidateSubmissionReceivedDateUtc,
                fa.FingerprintScores
            })
            .FirstOrDefault()
    })
    .SingleOrDefault(a => a.Id == request.ApplicationId);

移除fa.FingerprintScores后查询可正常执行。该属性是Attempts实体上的集合属性,定义如下:

private List<FingerprintScore> _fingerprintScores;

public List<FingerprintScore> FingerprintScores =>
    _fingerprintScores = _fingerprintScores ?? new List<FingerprintScore>();

通过SQL Server Profiler未发现请求到达数据库,推测异常发生在表达式树构建阶段。目前通过二次查询获取分数信息作为临时解决方案,但此类查询在代码库中大量存在,需要找到问题根源。

更新信息

通过LINQPad测试发现:

  • 移除fa.FingerprintScores或.FirstOrDefault()均可使查询正常执行
  • 所有相同关联关系的查询均存在该现象

以下是异常堆栈跟踪:

at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ShaperRemappingExpressionVisitor.GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ShaperRemappingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at Microsoft.EntityFrameworkCore.Query.CollectionShaperExpression.VisitChildren(ExpressionVisitor visitor)
   at Microsoft.EntityFrameworkCore.Query.SqlExpressions.SelectExpression.ShaperRemappingExpressionVisitor.VisitExtension(Expression extensionExpression)
   at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
   at System.Linq.Expressions.ExpressionVisitor.VisitNew(NewExpression node)
   at System.Linq.Expressions.ExpressionVisitor.VisitConditional(ConditionalExpression node)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.VisitNew(NewExpression newExpression)
   at Microsoft.EntityFrameworkCore.Query.Internal.RelationalProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
   at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
   at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass9_0`1.<Execute>b__0()
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore[TFunc](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)
   at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute[TResult](Expression query)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute[TResult](Expression expression)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.IEnumerable.GetEnumerator()
   at LINQPad.UI.ExplorerGrid.ConvertToList(IEnumerable source)
   at LINQPad.UI.ExplorerGrid.UpdateDataSourceToUse()

问题根源及解决办法

1. 属性定义不符合EF Core要求

EF Core对实体集合属性的定义有更严格的解析规则。当前FingerprintScores使用表达式体属性且在getter中延迟初始化集合,这种写法在EF 6中可行,但EF Core的查询表达式树解析器无法正确处理该逻辑,导致翻译过程中出现键查找失败。

解决:修改集合属性的初始化方式,改为在字段声明时或构造函数中初始化:

private List<FingerprintScore> _fingerprintScores = new List<FingerprintScore>();

public List<FingerprintScore> FingerprintScores => _fingerprintScores;

或者使用自动属性:

public List<FingerprintScore> FingerprintScores { get; set; } = new List<FingerprintScore>();

2. EF Core 3.1的查询翻译局限性

EF Core 3.1对「嵌套查询+集合投影」的支持存在bug,尤其是在FirstOrDefault()嵌套中直接包含集合属性时,表达式树翻译器会出现字典键缺失的异常(对应堆栈中的Dictionary.get_Item调用失败)。

解决:

  • 升级EF Core版本:EF Core 3.1是旧版本,后续的5.0+版本修复了大量查询翻译bug,升级到LTS版本(如6.0或8.0)可直接解决此类问题。
  • 调整查询写法:避免在嵌套投影中直接包含集合属性,可先通过Include预加载关联数据,再在内存中完成投影:
var data = context.Applications
    .Include(a => a.Attempts)
        .ThenInclude(fa => fa.FingerprintScores)
    .SingleOrDefault(a => a.Id == request.ApplicationId);

var result = new 
{
    data.Id,
    Attempt = data.Attempts
        .Select(fa => new
        {
            fa.CandidateSubmissionReceivedDateUtc,
            fa.FingerprintScores
        })
        .FirstOrDefault()
};

内容的提问来源于stack exchange,提问作者Craig W.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 07:03:17