LINQ 查询引发客户端评估错误
LINQ query throws client side evaluation error
最近一直在研究 EF Core 6,我遇到了一个客户端评估错误,我想知道是否有任何方法可以更有效地重写它。
我需要根据 TagIds
的列表查询一些 Photos
。例如,当按标签 [Portugal,Beach] 过滤时,需要获取包含 所有这些标签 的所有照片。所以带有 [葡萄牙,海滩,美食] 的照片 X 将被包括在内,但照片 Y [葡萄牙] 将被排除在外。
我相信我需要实现这样的目标,但这会引发客户端评估异常:
_context.Photo
.Include(i => i.PhotoTags)
.ThenInclude(j => j.Tag)
.Where(i => filter.tagIds.All(j => i.PhotoTags.Exists(k => k.TagId == j)))
与以下 类:
public class Photo
{
public Guid Id { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
public bool IsCover { get; set; }
public virtual List<PhotoTag> PhotoTags { get; set; }
}
public class PhotoTag : Base
{
public Guid Id { get; set; }
public Tag Tag { get; set; }
public Guid TagId { get; set; }
public Photo Photo { get; set; }
public Guid PhotoId { get; set; }
}
编辑
这是我遇到的错误:
System.InvalidOperationException: The LINQ expression 'j => MaterializeCollectionNavigation(
Navigation: Photo.PhotoTags,
subquery: DbSet<PhotoTag>()
.Where(p0 => EF.Property<Guid?>(EntityShaperExpression:
rvc.Models.Photo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id") != null && object.Equals(
objA: (object)EF.Property<Guid?>(EntityShaperExpression:
rvc.Models.Photo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id"),
objB: (object)EF.Property<Guid?>(p0, "PhotoId")))).Exists(k => k.TagId == j)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitLambda[T](Expression`1 lambdaExpression)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.TranslateInternal(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLambdaExpression(ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
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.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.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at rvc.Services.PhotoService.GetAll(FilterParameters filter) in C:\Users\jjtfs\Work\rvc\server\Services\PhotoService.cs:line 145
这可以通过计算过滤器中的标签以可翻译的形式重写。此计数应等于过滤器中的项目数:
var count = filter.tagIds.Count();
var result = _context.Photo
.Include(p => p.PhotoTags)
.ThenInclude(pt => pt.Tag)
.Where(p => p.PhotoTags.Count(pt => filter.tagIds.Contains(pt.TagId)) == count);
最近一直在研究 EF Core 6,我遇到了一个客户端评估错误,我想知道是否有任何方法可以更有效地重写它。
我需要根据 TagIds
的列表查询一些 Photos
。例如,当按标签 [Portugal,Beach] 过滤时,需要获取包含 所有这些标签 的所有照片。所以带有 [葡萄牙,海滩,美食] 的照片 X 将被包括在内,但照片 Y [葡萄牙] 将被排除在外。
我相信我需要实现这样的目标,但这会引发客户端评估异常:
_context.Photo
.Include(i => i.PhotoTags)
.ThenInclude(j => j.Tag)
.Where(i => filter.tagIds.All(j => i.PhotoTags.Exists(k => k.TagId == j)))
与以下 类:
public class Photo
{
public Guid Id { get; set; }
public string Description { get; set; }
public DateTime Date { get; set; }
public bool IsCover { get; set; }
public virtual List<PhotoTag> PhotoTags { get; set; }
}
public class PhotoTag : Base
{
public Guid Id { get; set; }
public Tag Tag { get; set; }
public Guid TagId { get; set; }
public Photo Photo { get; set; }
public Guid PhotoId { get; set; }
}
编辑
这是我遇到的错误:
System.InvalidOperationException: The LINQ expression 'j => MaterializeCollectionNavigation(
Navigation: Photo.PhotoTags,
subquery: DbSet<PhotoTag>()
.Where(p0 => EF.Property<Guid?>(EntityShaperExpression:
rvc.Models.Photo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id") != null && object.Equals(
objA: (object)EF.Property<Guid?>(EntityShaperExpression:
rvc.Models.Photo
ValueBufferExpression:
ProjectionBindingExpression: EmptyProjectionMember
IsNullable: False
, "Id"),
objB: (object)EF.Property<Guid?>(p0, "PhotoId")))).Exists(k => k.TagId == j)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitLambda[T](Expression`1 lambdaExpression)
at System.Linq.Expressions.Expression`1.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.TranslateInternal(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalSqlTranslatingExpressionVisitor.Translate(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateExpression(Expression expression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateLambdaExpression(ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression)
at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.TranslateWhere(ShapedQueryExpression source, LambdaExpression predicate)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.VisitMethodCall(MethodCallExpression methodCallExpression)
at System.Linq.Expressions.MethodCallExpression.Accept(ExpressionVisitor visitor)
at System.Linq.Expressions.ExpressionVisitor.Visit(Expression node)
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.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.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at rvc.Services.PhotoService.GetAll(FilterParameters filter) in C:\Users\jjtfs\Work\rvc\server\Services\PhotoService.cs:line 145
这可以通过计算过滤器中的标签以可翻译的形式重写。此计数应等于过滤器中的项目数:
var count = filter.tagIds.Count();
var result = _context.Photo
.Include(p => p.PhotoTags)
.ThenInclude(pt => pt.Tag)
.Where(p => p.PhotoTags.Count(pt => filter.tagIds.Contains(pt.TagId)) == count);