簡體   English   中英

從 EF 6 轉換為 EF Core,現有查詢拋出“字典中不存在給定鍵”

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

我正在將我們的一個 .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查詢執行得很好。 使用結果集中的該屬性,查詢將引發KeyNotFoundException 它是Attempts實體上的一個集合屬性,定義如下:

private List<FingerprintScore> _fingerprintScores;

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

使用 SQL Server Profiler 永遠不會顯示訪問數據庫的請求,所以我假設它正在嘗試構建表達式樹,而不是與它試圖檢索的數據相關的東西。

現在我已經通過第二次查詢來獲取分數信息解決了這個問題,但是我們在整個代碼庫中都在做這種事情,所以我想更好地了解出了什么問題。

更新

使用 LINQPad 嘗試不同的組合我發現刪除fa.FingerprintScoresfa.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()

嘗試以下查詢。 它強制 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