EF Core Global Query Filters: A Complete Guide

posted 2 min read

Entity Framework Core (EF Core) Global Query Filters allow you to apply filters to queries at the model level so that they automatically apply to all queries involving a specific entity.

This is particularly useful for scenarios like soft deletes, multi-tenancy, and user-based data filtering.

What is a Global Query Filter?

A global filter is a LINQ predicate that applies automatically to all queries on a specific entity type.

This means that any time you query the database, EF Core applies the filter implicitly, reducing the need for adding Where clauses manually.

Use Cases

  • Soft Deletes – Automatically filter out entities where IsDeleted =
    true.

  • Multi-Tenancy – Ensure that a tenant only accesses their own data.

  • User-Based Filtering – Restrict users to see only their own records.

How to Define a Global Query Filter

Global filters are defined in the OnModelCreating method inside the DbContext class using the HasQueryFilter method.

Example : Soft Delete Implementation ..

public class BaseEntity
{
    public bool IsDeleted { get; set; }
}

public class Product : BaseEntity
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class AppDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>()
            .HasQueryFilter(p => !p.IsDeleted);
    }
}

Now, every query on Products automatically filters out records where IsDeleted = true.

Querying Products

var products = context.Products.ToList(); // Implicitly applies "WHERE IsDeleted = 0"

Bypassing the Global Filter

You can explicitly disable the filter using .IgnoreQueryFilters().

var allProducts = context.Products.IgnoreQueryFilters().ToList();

Applying Filters Dynamically (Multi-Tenancy Example)

public class AppDbContext : DbContext
{
    private readonly int _tenantId;

    public AppDbContext(DbContextOptions<AppDbContext> options, ITenantProvider tenantProvider)
        : base(options)
    {
        _tenantId = tenantProvider.GetTenantId();
    }

    public DbSet<Order> Orders { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>()
            .HasQueryFilter(o => o.TenantId == _tenantId);
    }
}

Now, EF Core automatically filters records based on _tenantId.

Limitations and Considerations

  • Filters do not apply to raw SQL queries (FromSqlRaw).

  • Navigation properties respect global filters (e.g., if Order has OrderDetails, the filter applies to them too).

  • Ensure filters do not cause unexpected performance issues on large datasets.

  • You can define multiple query filters per entity.

Combining Multiple Filters

modelBuilder.Entity<Product>()
    .HasQueryFilter(p => !p.IsDeleted)
    .HasQueryFilter(p => p.Status == "Active");

This results in:

SELECT * FROM Products WHERE IsDeleted = 0 AND Status = 'Active'

Disabling All Global Filters

You can disable all filters for a specific context query using:

context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

or

var allOrders = context.Orders.IgnoreQueryFilters().ToList();

Conclusion
EF Core’s Global Query Filters help enforce consistent rules across queries without adding redundant Where clauses. They are a powerful feature for soft deletes, multi-tenancy, and user-based access control. However, they should be used carefully, considering potential performance impacts.

Source Code

You can find the complete source code for this tutorial at:
GitHub Repository

Here are some useful references to learn more about EF Core Global Query Filters and Soft Delete:

Official EF Core Documentation
Global Query Filters
https://learn.microsoft.com/en-us/ef/core/querying/filters

Entity Framework Core SQLite Provider
https://learn.microsoft.com/en-us/ef/core/providers/sqlite/

Managing Data with EF Core
https://learn.microsoft.com/en-us/ef/core/

Community Articles & Tutorials
EF Core: Global Query Filters for Soft Deletes
https://www.thinktecture.com/en/entity-framework-core/global-query-filters/

Implementing Soft Delete in EF Core
https://medium.com/swlh/soft-delete-in-entity-framework-core-6c6b7a9784c7

Using SQLite with EF Core in Console Applications
https://code-maze.com/using-sqlite-with-entity-framework-core/

If you read this far, tweet to the author to show them you care. Tweet a Thanks
solid breakdown of Global Query Filters! really appreciate the effort in explaining soft deletes and multi-tenancy so clearly. One thing I’m curious about—do global filters have any performance drawbacks when dealing with massive datasets? Like, does EF Core optimize these queries well, or could they slow things down in certain scenarios? I love to hear your thoughts...:-)
That’s a great question, and I really appreciate your comment! As I mentioned, global query filters are a powerful feature for soft deletes, multi-tenancy, and user-based access control. However, they should be used carefully, as they can have performance implications.

To mitigate potential issues, certain optimizations are necessary—SQL indexing is a must to ensure efficient filtering. Since global filters are evaluated in the database rather than in memory, they generally improve performance. However, for complex queries with many joins or aggregations, global filters might introduce inefficiencies, and in such cases, it may be beneficial to disable them selectively when needed.

More Posts

EF Core: Lazy Loading, Eager Loading, and Loading Data on Demand

Spyros - Mar 6

When NOT to Use AsSplitQuery() in EF.core

Spyros - Feb 26

Rate limiting middleware in ASP.NET Core using .NET 8.0

Hussein Mahdi - May 11, 2024

What's New in .NET Aspire 9.1

Barret Blake - Mar 13

Suitable DB Choice in USSD Application

Moses Korir - Mar 12
chevron_left