Skip to content

EF11 Regression: EF.Parameter/EF.Constant on a context property in a query filter now throws (non-compiled queries) #39081

Description

@wassim-k

Bug description

#38155 added a !_parameterize check to ExpressionTreeFuncletizer so that EF.Constant, EF.Parameter and EF.MultipleParameters throw in compiled queries and query filters. Query filters are also funcletized with parameterize: false. As a result, ordinary non-compiled queries now fail when an entity's query filter uses one of these methods on a context property. This pattern worked before #38155.

Repro

public class BlogContext(DbContextOptions options) : DbContext(options)
{
    public int TenantId { get; set; } = 1;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        => modelBuilder.Entity<Blog>()
            .HasQueryFilter(e => e.TenantId == EF.Parameter(TenantId)); // same with EF.Constant(TenantId)
}

context.Set<Blog>().ToList();

Before #38155: the query runs and returns only the rows for TenantId == 1.

After #38155:

System.InvalidOperationException: 'EF.Parameter<T>' is not supported when using compiled queries or query filters.
   at ExpressionTreeFuncletizer.<VisitMethodCall>g__HandleParameter|40_1(...)
   at NavigationExpandingExpressionVisitor.ApplyQueryFilter(...)

Your code

The following test can be added to AdHocQueryFiltersQueryTestBase. It fails on main with InvalidOperationException: 'EF.Parameter<T>' is not supported when using compiled queries or query filters. and passes when the !_parameterize checks added in #38155 are removed.

[Fact]
public virtual async Task Non_compiled_query_with_EF_Parameter_in_query_filter_over_context_property()
{
    var contextFactory = await InitializeNonSharedTest<Context_ParameterFilter>(seed: c => c.SeedAsync());
    using var context = contextFactory.CreateDbContext();

    Assert.Equal([1, 2], context.Set<Entity>().OrderBy(e => e.Id).Select(e => e.Id).ToList());
}

protected class Context_ParameterFilter(DbContextOptions options) : DbContext(options)
{
    public int TenantId { get; set; } = 1;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        => modelBuilder.Entity<Entity>()
            .HasQueryFilter(e => e.TenantId == EF.Parameter(TenantId)); // same with EF.Constant(TenantId)

    public Task SeedAsync()
    {
        AddRange(
            new Entity { Id = 1, TenantId = 1 },
            new Entity { Id = 2, TenantId = 1 },
            new Entity { Id = 3, TenantId = 2 });

        return SaveChangesAsync();
    }
}

public class Entity
{
    public int Id { get; set; }
    public int TenantId { get; set; }
}

Note: the existing tests Query_filter_with_EF_Parameter_throws and Query_filter_with_EF_Constant_throws use this same context-property pattern and would need to be removed or changed.

EF Core version

11 RC1

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions