【发布时间】:2020-04-28 03:22:03
【问题描述】:
我将我的数据层类库项目从 .NETCore 2.2 升级到 .NETCore3.1,还将 Nuget 包(如 EntityFrameWork Core)从 2.2.0 升级到 EFCore 3.1.0。
然后我在验证以下代码时遇到如下错误:
代码:
private async Task<List<CountryDTO>> GetCountriesDataAsync(int languageId)
{
int pageNo = 1, pageSize = 100;
var images = await _cacheService.GetAllAsync("imagesCacheKey");
return await _dbContext.Countries
.Where(cc => cc.IsPublished.Equals(true)
&& cc.LanguageId.Equals(languageId))
.Select(co => new CountryDTO
{ Uuid = co.CountryId,
PNGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(co.PNGImageId))
.FilePath,
SVGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(co.SVGImageId))
.FilePath,
DisplayName = co.DisplayName,
DisplayNameShort = co.DisplayName,
Name = Helper.ReplaceChars(co.DisplayName),
Path = Helper.ReplaceChars(co.DisplayName),
CompleteResponse = true})
.Skip((pageNo - 1) * 100)
.Take(pageSize)
.ToListAsync();
}
错误:
When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type. Alternatively, override 'VisitLambda' and change it to not visit children of this type.
---> System.InvalidOperationException: When called from 'VisitLambda', rewriting a node of type 'System.Linq.Expressions.ParameterExpression' must return a non-null value of the same type. Alternatively, override 'VisitLambda' and change it to not visit children of this type.
at System.Linq.Expressions.ExpressionVisitor.VisitAndConvert[T](T node, String callerName)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitParameters(ExpressionVisitor visitor, IParameterProvider nodes, String callerName)
at System.Linq.Expressions.ExpressionVisitor.VisitLambda[T](Expression`1 node)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.Visit(Expression expression)
at System.Dynamic.Utils.ExpressionVisitorUtils.VisitArguments(ExpressionVisitor visitor, IArgumentProvider nodes)
at System.Linq.Expressions.ExpressionVisitor.VisitMethodCall(MethodCallExpression node)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.VisitMember(MemberExpression memberExpression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.VisitMemberAssignment(MemberAssignment memberAssignment)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.VisitMemberInit(MemberInitExpression memberInitExpression)
at System.Linq.Expressions.MemberInitExpression.Accept(ExpressionVisitor visitor)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.Visit(Expression expression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosProjectionBindingExpressionVisitor.Translate(SelectExpression selectExpression, Expression expression)
at Microsoft.EntityFrameworkCore.Cosmos.Query.Internal.CosmosQueryableMethodTranslatingExpressionVisitor.TranslateSelect(ShapedQueryExpression source, LambdaExpression selector)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
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__DisplayClass12_0`1.<ExecuteAsync>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.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)
at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()
at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
at Author.Query.Persistence.CountryService.GetCountriesDataAsync(Int32 languageId) in /src/QueryStack/Author.Query.Persistence/CountryService.cs:line 243
at Author.Query.Persistence.CountryService.GetCountriesAsync(Int32 dftLanguageId, Int32 localeLangId) in /src/QueryStack/Author.Query.Persistence/CountryService.cs:line 228
at Author.Query.Persistence.CountryService.GetAllCountriesAsync(LanguageDTO language) in /src/QueryStack/Author.Query.Persistence/CountryService.cs:line 164
at GraphQL.DataLoader.DataLoaderBase`1.DispatchAsync(CancellationToken cancellationToken)
at Author.Query.New.API.GraphQL.Resolvers.CountriesResolver.<>c__DisplayClass5_1.<<Resolve>b__3>d.MoveNext() in /src/QueryStack/Author.Query.New.API/GraphQL/Resolvers/CountriesResolver.cs:line 40
--- End of stack trace from previous location where exception was thrown ---
at GraphQL.Types.ResolveFieldContext`1.TryAsyncResolve[TResult](Func`2 resolve, Func`2 error)
--- End of inner exception stack trace ---
任何人都可以通过提供解决此问题的指导来帮助我吗?
【问题讨论】:
-
你已经有一个错误。此查询根本无法转换为 SQL,因为它调用 本地函数。 EF Core 2.2 的客户端执行通过将几乎所有内容拉到客户端并在那里评估其余查询来掩盖错误。这会通过加载比需要更多的记录和/或在只需要少数列时加载所有列而严重损害性能。修复(非常难以阅读!)查询,使其不使用任何本地函数。
-
顺便说一句,如果您启用了 EF Core 2.x 日志记录,您会看到 EF 在运行时已经发出警告
-
不只是
Helper.ReplaceChar破坏了这个查询。images.FirstOrDefault(...)搜索本地集合。无法将其转换为 SQL。查询是如此复杂,尽管 LINQ 提供程序在尝试将其转换为 SQL 之前因该错误而失败 -
images.FirstOrDefault也不应该使用。您只是通过 ImageId 查找 FilePath。当前代码扫描所有图像以找到匹配的图像。使用字典代替仅保存 ImageID 和 FilePath 值,并使用Dictionary.TryGetValue查找路径,例如images.TryGetValue(co.PNGImageID,out var img)? img.FileName:null -
感谢@PanagiotisKanavos 的回复。根据您的输入,我已经更新了代码,它对我有用:)
标签: linq azure-cosmosdb c#-8.0 .net-core-3.1 ef-core-3.1