Global Query Filters in EF Core 2.0

Global Query Filters are a new addition to the arsenal of features in EF Core 2.0. This also implies that EF core team spearheaded by Diego Vega who are working diligently to bring EF Core at par with its Entity Framework 6.x classic counterpart. Like it or not, its good news for us developers, right?

Well, GQF in short are LINQ query predicates. In other words they are a boolean expression that are typically passed to the LINQ “Where” query operator and applied to Entity Types in the metadata model (usually in OnModelCreating). Such filters are automatically applied to any LINQ queries involving those Entity Types, including Entity Types referenced indirectly, such as through the use of Include or direct navigation property references.

Below is a Snapshot of the database containing two tables i.e. Department & Employee respectively.

GQFContext.cs class

namespace GlobalQueryFilters 
{
    class GQFContext : DbContext
    {
        public DbSet Department { get; set; }
        public DbSet Employee { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(@"server=Obi-Oberoi; database=Company; Trusted_Connection=True;");
        }

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

    }

Department & Employee POCO Classes

using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace GlobalQueryFilters
{
    public class Department
    {
        [Key]
        public int DepartmentID { get; set; }
        public string Name { get; set; }
        public List Employee { get; set; }
    }

    public class Employee
    {
        [Key]
        public int ID { get; set; }
        [ForeignKey("DepartmentID")]
        public int DepartmentID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Gender { get; set; }
        public decimal Salary { get; set; }
        public bool IsDeleted { get; set; }
        public Department Department { get; set; }
    }
}

Program.cs

 
static void Main(string[] args)
        {
            using (var ctx =  new GQFContext())
            {
                var emp = ctx.Employee.ToList();

                foreach (var item in emp.Where(e => e.DepartmentID == 3))
                {
                    Console.WriteLine("Name = {0},{1}", item.FirstName, item.LastName);
                }
                Console.ReadLine();
            }
        }

Notice the two records with the DepartmentID of 3 that are being filtered using the LINQ query above.

Now, let’s try and do something different. Let’s query the records with DepartmentID of 2. In the Employee table, we have at least two records with DepartmentID of 2. See below:

Notice the record for the employee Steve Pound has one of his records marked for deletion. That’s precisely what we intended for when using Global Query Filter which as you can recall from the code snippet below. This code is defined in the GQFContext class where we have specifically filtered the record(s) that are marked for soft deletionΒ  like so:

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

Notice, the record Steve Pound is filtered as a result of Global Query Filter that is defined as a predicate in the “HasQueryFilter” method.

About Obi Oberoi

Obi Oberoi is an Independent Consultant, Developer and a Life-Long student of continuous learning. Obi enjoys to code, read, and hang out with techies and geeks!
This entry was posted in ORM. Bookmark the permalink.