Entity Framework Query Filters
NOTE: This is information is taken from a variety of resources and experience. Particular mentions to Milan Jovanović.
Overview
Global Query Filters in Entity Framework Core are predefined LINQ predicates applied directly to an entity type within the DbContext model configuration. Once established, these filters are automatically and implicitly appended to all queries executed against those specific entities. This feature is essential for implementing systemic, application-wide data access rules—such as "soft delete" patterns (e.g., universally hiding records where IsDeleted == true) or multi-tenant architectures (e.g., restricting data access to the current TenantId)—ensuring consistent data isolation without the need to manually add .Where() clauses to every individual query throughout your codebase.
Without Query Filters
Suppose we have an entity class with an IsDeleted property:
public class Order
{
public int Id { get; set; }
public bool IsDeleted { get; set; }
}
If we want to list only the records where IsDeleted == false, an EF quert to return a single entity could take the form:
dbContext
.Orders
.Where(order => !order.IsDeleted)
.Where(order => order.Id == orderId)
.FirstOrDefault();
That works great, but we have to remember to apply this to every query we write.
How To Apply Query Filters
We can define a Query Filter on the Order entity to apply this check when querying the database.
Inside of the OnModelCreating method on the database context, we need to call the HasQueryFilter method and specify the expression we want:
modelBuilder
.Entity<Order>()
.HasQueryFilter(order => !order.IsDeleted);
Now we can omit the soft-delete check from the previous LINQ expression:
dbContext
.Orders
.Where(order => order.Id == orderId)
.FirstOrDefault();
Which results in the following SQL:
SELECT o.*
FROM Orders o
WHERE o.IsDeleted = FALSE AND o.Id = @orderId
Disabling Query Filters
For a situation where you need to disable Query Filters for a specific query you need to call the IgnoreQueryFilters method, and all the Query Filters configured for this entity will be disabled:
dbContext
.Orders
.IgnoreQueryFilters()
.Where(order => order.Id == orderId)
.FirstOrDefault();
Be careful when doing this, as you can easily introduce unwanted behaviour in your application.
Multiple Query Filters
Configuring multiple Query Filters on the same entity will only apply the last one. If you need more than one condition, you can do that with the logical AND operator (&&).
Ignoring specific Query Filters
If you need to ignore a specific expression in a Query Filter and leave the rest in place you will have to remove the configured Query Filter for that entity type (as there can be only one), and then manually apply the condition that you need for that specific query.