从“VisitLambda”调用时,重写“System.Linq.Expressions.ParameterExpression”类型的节点必须返回同一类型的非空值

iecba09b  于 2023-05-04  发布在  其他
关注(0)|答案(3)|浏览(191)

我将我的数据层类库项目从.NETCore 2.2升级到.NETCore3.1,并将EntityFrameWork Core等Nuget包从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 ---

有人可以帮助我在这里提供他们的指导来解决这个问题吗?

k4aesqcs

k4aesqcs1#

这里有几个问题很容易解决,将query int分为两半,第一个是查询数据库并返回部分填充的CountryDTO的列表,第二个是遍历填充缺失项的列表:

private async Task<List<CountryDTO>> GetCountriesDataAsync(int languageId)
{
            int pageNo = 1, pageSize = 100;

            var results = _dbContext.Countries // <- do not use await on db context
                    .Where(cc => cc.IsPublished.Equals(true)
                      && cc.LanguageId.Equals(languageId))
                    .Select(co => new {
                        co.CountryId,
                        co.DisplayName,
                        co.PNGImageId,
                        co.SVGImageId
                    })
                     .Skip((pageNo - 1) * pageSize) // <- use page size no 100
                     .Take(pageSize)
                     .ToListAsync();

            var images = await _cacheService.GetAllAsync("imagesCacheKey");

            return Task.FromResult( results.Select(co => new CountryDTO
            {
                Uuid = co.CountryId,
                PNGImagePath = images.FirstOrDefault(im => im.ImageId.Equals(co.PNGImageId))?.FilePath, // <- could be null so use ?.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
            }).ToList());

}

我创建了一个匿名类型来保存数据库的返回值,而不是向DTO添加额外的字段来保存图像ID等。如果你需要从数据库中获取更多信息,只需在context select语句中将字段添加到匿名类型。

shstlldc

shstlldc2#

这个错误刚刚发生在我身上,对于未来的访问者,我做错了什么:
我有两个模型,例如:

public User
{
    public int Id {get; set;}
    public string Name {get; set;}
    //just a silly method that does something
    public string GetName()
    {
      return this.Name + "something"
    }
}
public UserInfo
{
    public int Id {get; set;}
    // a bunch of other properties
}

在代码的某个地方我用自动Map器做了一个投影

Mapper.ProjectTo<UserInfo>(Repository.Get().ByUserName(userId)).FirstOrDefault();

这个错误When called from 'VisitLambda',...开始显示时,我插入的GetName方法,不知何故打破了projectToMap。

oknrviil

oknrviil3#

我的情况有点不同,但完全相同的错误:* “从'VisitLambda'调用时,重写类型为'System.Linq.Expressions.ParameterExpression'的节点必须返回同一类型的非空值”*

但是,我的集合是分开的,我没有在同一个数据库调用上运行投影。我检索了一个IQueryable<MyType>集合,然后将Select投影到我的视图模型。我在投影中也没有使用任何局部函数。
所以,发生的事情是我在同一个投影中使用了两个不同的集合。我有一个IQueryable<DbSet<T>>集合,以及从数据库中存储的某个DTO的不同列表。因此,它抛出“必须是***相同类型的值***”的异常是有意义的。

问题是使用了另一个DTO列表:

collection.Select(s => new MyDataClass(s.Id, s.Name, otherDTOList.Find(...) ...
我的解决方案是在投影中使用外键引用,而不是尝试使用额外的DTO列表,因为FK表数据是在join中检索的:
collection.Select(s => new MyDataClass(s.Id, s.Name, s.MyFKClass.Find(...
奇怪的情况下,如果有一种方法可以做到这一点与两个集合,请让我知道!

相关问题