Entity Framework Core 2: Model-level query filters

When we query data through Entity Framework Core 2.0, it’s completely normal to want to filter this data. If for a given type or model we have a filter that we are going to apply in different places, we could configure Entity Framework so that that filter always get applied. This filter will be applied by defect. Of course, we also are able to tell Entity Framework when it should ignore such default filter.

This concept is called Model-level query filter. In summary, in our class that inherits from DbContext, we are going to indicate a filter that will be applied anytime we query that type, unless we indicate explicitly that we don’t want that filter to be applied. This functionality was added on Entity Framework Core 2.0. Let’s see an example of this.

Example

Let’s suppose we have a model with a Boolean property called “IsDeleted”:

class Student
 {
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public bool IsDeleted { get; set; }
 }

We want that anytime we use a query that involves the Student model, a filter is applied such that we only get the records that have the value of the column IsDeleted equal to false. Let’s use a Model-level query filter for this:

Step 1 – Go to your class that inherits from DbContext,

Step 2 – Use the OnModelCreating method to set the Model-level query filter:


protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
   modelBuilder.Entity<Student>().HasQueryFilter(x => x.IsDeleted == false);
}

As you can see, what we do is to use the Fluent API to configure the Student entity. Then we use the HasQueryFilter function to configure the model-level query filter. We pass as a paremeter the filter that we want applied everytime we do a query involving the Student model.

Now, if I make a simple query using the Student model:


using (var context = new ApplicationDbContext())
 {
    var students = context.Students.ToList();
 }

The following SQL query will be generated:


SELECT [e].[Id], [e].[Age], [e].[IsDeleted], [e].[Name]
 FROM [Students] AS [e]
 WHERE [e].[IsDeleted] = 0

Notice the [e].[IsDeleted] = 0, that filter is not on the select I did with Entity Framework, but because we defined the model-level query filter, everytime we make a query with Entity Framework involving the Student model, said filter gets applied.

If by any reason, we don’t want the filter to be applied for a specific query, we can use the IgnoreQueryFilters function. Like this:


using (var context = new ApplicationDbContext())
{
   var estudents = context.Students.IgnoreQueryFilters().ToList();
}

In this case, the generated query is the following one:


SELECT [e].[Id], [e].[Age], [e].[IsDeleted], [e].[Name]
FROM [Students] AS [e]

As you can see, the Where clause is not present in the last query, because we used the IgnoreQueryFilters function to avoid the model-level query filter from being used on the Student model.

Conclusion

Use model-level query filters when you want that, by defect, a filter gets applied when you do a query with Entity Framework using a specific model. You have the ability also to avoid such filter in determined instances if you require to.

One comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s