简体   繁体   English

从 EF 6 转换为 EF Core,现有查询抛出“字典中不存在给定键”

[英]Converting from EF 6 to EF Core, existing query throwing "given key was not present in the dictionary"

I'm in the process of converting one of our .NET Framework applications from EF 6 to EF Core (3.1.26).我正在将我们的一个 .NET Framework 应用程序从 EF 6 转换为 EF Core (3.1.26)。 One of our queries is now throwing a KeyNotFoundException .我们的一个查询现在抛出一个KeyNotFoundException

The query in question is shown here:此处显示有问题的查询:

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);

If I remove fa.FingerprintScores the query executes fine.如果我删除fa.FingerprintScores查询执行得很好。 With that property in the result set the query throws the KeyNotFoundException .使用结果集中的该属性,查询将引发KeyNotFoundException It is a collection property on the Attempts entity and is defined as follows:它是Attempts实体上的一个集合属性,定义如下:

private List<FingerprintScore> _fingerprintScores;

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

Using SQL Server Profiler never shows the request hitting the database so I'm assuming it's blowing up trying to build the expression tree and not something related to the data it's trying to retrieve.使用 SQL Server Profiler 永远不会显示访问数据库的请求,所以我假设它正在尝试构建表达式树,而不是与它试图检索的数据相关的东西。

For now I've resolved the issue by doing a second query to get the score information, but we do this sort of thing throughout the codebase so I'd like to have a better idea of what's going wrong.现在我已经通过第二次查询来获取分数信息解决了这个问题,但是我们在整个代码库中都在做这种事情,所以我想更好地了解出了什么问题。

UPDATE更新

Using LINQPad to try out different combinations I discovered that removing either the fa.FingerprintScores or the .FirstOrDefault() causes the query to work.使用 LINQPad 尝试不同的组合我发现删除fa.FingerprintScoresfa.FingerprintScores .FirstOrDefault()会导致查询工作。 I can reproduce that behavior consistently in any queries that have the same type of relationships.我可以在具有相同类型关系的任何查询中一致地重现该行为。

As someone asked in the comments, here is the stack trace.正如评论中有人问的那样,这里是堆栈跟踪。

   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()

Try the following query.尝试以下查询。 It forces EF Core to use different translation algorithm but give the same result.它强制 EF Core 使用不同的翻译算法,但给出相同的结果。

var query = 
    from a in context.Applications
    from fa in a.Attempts
        .Select(fa => new
        {
            fa.CandidateSubmissionReceivedDateUtc,
            fa.FingerprintScores
        })
        .Take(1)
        .DefaultIfEmpty()
    select new 
    {
        a.Id,
        Attempt = fa
    };    

var data = query
    .SingleOrDefault(a => a.Id == request.ApplicationId);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM