# Named Query Filters in EF 10 (multiple query filters per entity)

> EF 10 introduces named query filters, letting you attach multiple filters to a single entity and disable specific ones without turning off all query filters. This article shows how to combine soft deletion and multi-tenancy, with best practices like constants for filter names.

Published: 2025-07-26. Author: Milan Jovanović.

Canonical: https://milanjovanovic.tech/blog/named-query-filters-in-ef-10-multiple-query-filters-per-entity

**Named query filters** are a feature EF 10 introduced: you attach multiple global query filters to one entity by passing a name to `HasQueryFilter`.
You can then disable individual filters by name with `IgnoreQueryFilters` instead of turning them all off at once.
That makes combinations like soft deletion plus multi-tenancy much safer.

Entity Framework Core's global query filters have long been a convenient way to apply common conditions to all queries on an entity.
They're especially handy in scenarios like [**soft deletion**](https://milanjovanovic.tech/blog/implementing-soft-delete-with-ef-core)
and [**multi-tenancy**](https://milanjovanovic.tech/blog/multi-tenant-applications-with-ef-core),
where you want the same `WHERE` clause added automatically to every query.

Previous versions of EF Core, however, suffered from **one big limitation**: each entity type could only have one filter defined.
If you needed to combine multiple conditions (for example, soft-delete and tenant isolation)
you either had to write explicit `&&` expressions or manually disable and reapply filters in specific queries.

With EF 10, that changes.
The new **named query filters** feature lets you attach multiple filters to a single entity and reference them by name.
You can then disable individual filters as needed, rather than turning off all filters at once.

Let's explore this new capability, why it matters, and some practical ways to use it.

## What Are Query Filters?

If you've used EF Core for a while, you may already be familiar with
[global query filters](https://learn.microsoft.com/en-us/ef/core/querying/filters).
A query filter is a condition that EF automatically applies to all queries for a particular entity type.
Under the hood, EF adds a `WHERE` clause whenever that entity is queried. Typical uses include:

- **Soft deletion**: filtering out rows where IsDeleted is true so that deleted records don't show up in queries by default
- **Multi-tenancy**: filtering by a TenantId so that each tenant only sees its own data

For example, a soft-delete filter might be configured like this:

```csharp
modelBuilder.Entity<Order>()
    .HasQueryFilter(order => !order.IsDeleted);
```

With the filter in place, every query on `Orders` automatically excludes soft-deleted records.
To include deleted data (say, for an admin report), you can call `IgnoreQueryFilters()` on the query.
The downside is that all filters on that entity are disabled,
which opens the door to accidentally leaking data you don't intend to show.

## Using Multiple Query Filters

Until now, EF permitted only one query filter per entity.
If you called `HasQueryFilter` twice on the same entity, the second call overwrote the first.
To combine filters you had to write a single expression with `&&`:

```csharp
modelBuilder.Entity<Order>()
    .HasQueryFilter(order => !order.IsDeleted && order.TenantId == tenantId);
```

This works but makes it impossible to selectively disable one condition.
`IgnoreQueryFilters()` disables both, forcing you to manually re-apply whichever filter you still need.
EF 10 introduces a better alternative: **named query filters**.

To attach multiple filters to an entity, call `HasQueryFilter` with a name for each filter:

```csharp
modelBuilder.Entity<Order>()
    .HasQueryFilter("SoftDeletionFilter", order => !order.IsDeleted)
    .HasQueryFilter("TenantFilter", order => order.TenantId == tenantId);
```

Under the hood, EF creates separate filters identified by the names you provide.
You can now turn off just the soft-delete filter while keeping the tenant filter in place:

```csharp
// Returns all orders (including soft‑deleted) for the current tenant
var allOrders = await context.Orders.IgnoreQueryFilters(["SoftDeletionFilter"]).ToListAsync();
```

If you omit the parameter array, `IgnoreQueryFilters()` disables all filters for the entity.

## Tip: Using Constants for Filter Names

Named filters use string keys.
Hard-coding those names throughout your codebase makes it easy to introduce typos and brittle magic strings.
To avoid this, define constants or enums for your filter names and reuse them wherever needed.
For example:

```csharp
public static class OrderFilters
{
    public const string SoftDelete = nameof(SoftDelete);
    public const string Tenant = nameof(Tenant);
}

modelBuilder.Entity<Order>()
    .HasQueryFilter(OrderFilters.SoftDelete, order => !order.IsDeleted)
    .HasQueryFilter(OrderFilters.Tenant, order => order.TenantId == tenantId);

// Later in your query
var allOrders = await context.Orders.IgnoreQueryFilters([OrderFilters.SoftDelete]).ToListAsync();
```

Having the filter names defined in a single place reduces duplication and improves maintainability.
Another best practice is to wrap the ignore call in an extension method or repository
so that consumers don't directly interact with filter names at all. For example:

```csharp
public static IQueryable<Order> IncludeSoftDeleted(this IQueryable<Order> query)
    => query.IgnoreQueryFilters([OrderFilters.SoftDelete]);
```

This makes your intent explicit and centralizes the filter logic in one place.

## Wrapping Up

The introduction of **named query filters** in EF 10 removes one of the longstanding limitations
of EF's [**global query filters**](https://milanjovanovic.tech/blog/how-to-use-global-query-filters-in-ef-core) feature.
You can now:

- Attach multiple filters to a single entity and manage them individually
- Selectively disable specific filters in a LINQ query using `IgnoreQueryFilters(["FilterName"])`
- Simplify common patterns like [**soft deletion**](https://milanjovanovic.tech/blog/implementing-soft-delete-with-ef-core) plus
  [**multi-tenancy**](https://milanjovanovic.tech/blog/multi-tenant-applications-with-ef-core) without resorting to complicated conditional logic

Named query filters can become a powerful tool to keep your queries clean and your domain logic encapsulated.

Whether you're building SaaS applications that isolate tenant data or
ensuring that deleted records stay hidden until you explicitly need them,
EF 10's named query filters offer the flexibility you've been waiting for.

Give them a try in the preview and start thinking about how they can simplify your codebase.

That's all for today.

See you next week.

---

## Frequently asked questions

### What are named query filters in EF Core?

Named query filters are a feature EF 10 introduced (first available in its preview in 2025). You attach multiple global query filters to one entity by passing a name to HasQueryFilter, and you can later disable individual filters by name instead of turning them all off at once.

### Can an EF Core entity have multiple query filters?

Before EF 10, no. Each entity type allowed one filter, and a second HasQueryFilter call overwrote the first, so combining soft deletion with tenant isolation meant writing one expression joined with &&. EF 10 added named filters, letting you attach several filters and manage each independently.

### How do you disable only one query filter in EF Core?

With EF 10 named filters, pass the names you want disabled to IgnoreQueryFilters. For example, IgnoreQueryFilters(["SoftDeletionFilter"]) includes soft-deleted rows while the tenant filter stays active. Calling IgnoreQueryFilters() without arguments still disables every filter on the entity.

### What are global query filters used for in EF Core?

A global query filter is a condition EF automatically applies to every query for an entity type by adding a WHERE clause. The two typical uses are soft deletion, hiding rows where IsDeleted is true, and multi-tenancy, filtering by TenantId so each tenant only sees its own data.

### Why is IgnoreQueryFilters dangerous in multi-tenant applications?

Without named filters, IgnoreQueryFilters disables every filter on the entity. Turning off the soft-delete filter for an admin report also turns off tenant isolation, which can leak another tenant's data unless you manually re-apply the condition. EF 10's per-name disabling removed that failure mode.

### What is the best practice for naming EF Core query filters?

Filter names are string keys, so hard-coding them invites typos and magic strings. Define constants with nameof in a static class and reuse them, and wrap common calls in intention-revealing extension methods like IncludeSoftDeleted() so consumers never touch filter names directly.
