From c7e1061fc90f5327800a4baaaca701e01d9b11bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jiri=20Cincura=20=E2=86=B9?= Date: Sat, 30 Nov 2024 09:16:37 +0100 Subject: [PATCH 1/2] Fix query filters with context accessors (#35237) --- .../Internal/ExpressionTreeFuncletizer.cs | 6 ++- .../Query/AdHocQueryFiltersQueryTestBase.cs | 38 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs index a04ef3b8888..0e8bc0b0860 100644 --- a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs +++ b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs @@ -552,7 +552,11 @@ protected override Expression VisitConditional(ConditionalExpression conditional goto case StateType.ContainsEvaluatable; case StateType.ContainsEvaluatable: - // The case where the test is evaluatable has been handled above + if (testState.IsEvaluatable) + { + test = ProcessEvaluatableRoot(test, ref testState); + } + if (ifTrueState.IsEvaluatable) { ifTrue = ProcessEvaluatableRoot(ifTrue, ref ifTrueState); diff --git a/test/EFCore.Specification.Tests/Query/AdHocQueryFiltersQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/AdHocQueryFiltersQueryTestBase.cs index c9cd6ab37f2..6754eb275f3 100644 --- a/test/EFCore.Specification.Tests/Query/AdHocQueryFiltersQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/AdHocQueryFiltersQueryTestBase.cs @@ -730,4 +730,42 @@ public class ChildFilter2 } #endregion + + #region 35111 + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual async Task Query_filter_with_context_accessor_with_constant(bool async) + { + var contextFactory = await InitializeAsync(); + using var context = contextFactory.CreateContext(); + + var data = async + ? await context.Set().ToListAsync() + : context.Set().ToList(); + } + + protected class Context35111(DbContextOptions options) : DbContext(options) + { + public int Foo { get; set; } + public long? Bar { get; set; } + public List Baz { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity() + .HasQueryFilter(e => + Foo == 1 + ? Baz.Contains(e.Bar) + : e.Bar == Bar); + } + } + + public class FooBar35111 + { + public long Id { get; set; } + public long Bar { get; set; } + } + + #endregion } From 2b5b1575aec39e8ce9b47af86efe72f9a37ee522 Mon Sep 17 00:00:00 2001 From: Jiri Cincura Date: Mon, 2 Dec 2024 13:06:56 +0100 Subject: [PATCH 2/2] Add quirk. --- src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs index 0e8bc0b0860..3d70a71491f 100644 --- a/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs +++ b/src/EFCore/Query/Internal/ExpressionTreeFuncletizer.cs @@ -106,6 +106,9 @@ public class ExpressionTreeFuncletizer : ExpressionVisitor private static readonly bool UseOldBehavior35152 = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35152", out var enabled35152) && enabled35152; + private static readonly bool UseOldBehavior35111 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue35111", out var enabled35111) && enabled35111; + private static readonly MethodInfo ReadOnlyCollectionIndexerGetter = typeof(ReadOnlyCollection).GetProperties() .Single(p => p.GetIndexParameters() is { Length: 1 } indexParameters && indexParameters[0].ParameterType == typeof(int)).GetMethod!; @@ -554,7 +557,7 @@ protected override Expression VisitConditional(ConditionalExpression conditional case StateType.ContainsEvaluatable: if (testState.IsEvaluatable) { - test = ProcessEvaluatableRoot(test, ref testState); + test = UseOldBehavior35111 ? test : ProcessEvaluatableRoot(test, ref testState); } if (ifTrueState.IsEvaluatable)