dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.66k stars 3.15k forks source link

Combination of IgnoreQueryFilters with Max throws exception. #34682

Open mpapadis opened 3 days ago

mpapadis commented 3 days ago

I have a dbset and and I need to find max id in table, including soft deleted entries. For Max I need to the Max(this IQueryable source, string predicate, params object?[] args) If I don't use IgnoreQueryFilters I am getting the last not soft-deleted entry, as the true soft-deleted entry is excluded from setting HasQueryFilter(x => !x.IsDeleted) in the OnModelCreating sub of ModelBuilder. When I use IgnoreQueryFilters then I get an exception.

var max = dbSet.IgnoreQueryFilters().AsNoTracking().Max(keyName);

The exception I am getting is the following

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidOperationException: The LINQ expression 'DbSet<Statement>()
    .Max(s => Invoke(CallSite<Func<CallSite, object, object>>.Target, CallSite<Func<CallSite, object, object>>, s))' 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.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
   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 System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute(Expression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Execute(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Max(IQueryable source, ParsingConfig config, String predicate, Object[] args)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Max(IQueryable source, String predicate, Object[] args)

EF Core version: Database provider: Npgsql.EntityFrameworkCore.PostgreSQL Target framework: .NET 8.0 Operating system: Windows 11 Enterprise 22H2 22621.4169 IDE: Visual Studio 2022 17.11.3

roji commented 2 days ago

What's keyName? As always, a single line of code does not provide enough information to reproduce the issue. Please submit a minimal, runnable code sample.

satviktechie1986 commented 2 days ago

I have a dbset and and I need to find max id in table, including soft deleted entries. For Max I need to the Max(this IQueryable source, string predicate, params object?[] args) If I don't use IgnoreQueryFilters I am getting the last not soft-deleted entry, as the true soft-deleted entry is excluded from setting HasQueryFilter(x => !x.IsDeleted) in the OnModelCreating sub of ModelBuilder. When I use IgnoreQueryFilters then I get an exception.

var max = dbSet.IgnoreQueryFilters().AsNoTracking().Max(keyName);

The exception I am getting is the following

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
 ---> System.InvalidOperationException: The LINQ expression 'DbSet<Statement>()
    .Max(s => Invoke(CallSite<Func<CallSite, object, object>>.Target, CallSite<Func<CallSite, object, object>>, s))' 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.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
   at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)
   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 System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   --- End of inner exception stack trace ---
   at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(Object obj, Span`1 copyOfArgs, BindingFlags invokeAttr)
   at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute(Expression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Execute(MethodInfo operatorMethodInfo, IQueryable source, Expression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Execute(MethodInfo operatorMethodInfo, IQueryable source, LambdaExpression expression)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Max(IQueryable source, ParsingConfig config, String predicate, Object[] args)
   at System.Linq.Dynamic.Core.DynamicQueryableExtensions.Max(IQueryable source, String predicate, Object[] args)

EF Core version: Database provider: Npgsql.EntityFrameworkCore.PostgreSQL Target framework: .NET 8.0 Operating system: Windows 11 Enterprise 22H2 22621.4169 IDE: Visual Studio 2022 17.11.3

var max = dbSet.IgnoreQueryFilters().AsNoTracking().Max(s => EF.Property(s, keyName));

try this, might works

roji commented 2 days ago

Please take the time to submit a verified, minimal console program.