Skip to content
Michael B edited this page Oct 20, 2021 · 18 revisions

Overview

NPredicateBuilder is a library that allows you to build queries for Entity Framework that are built to be easily testable, modular, and reduce repetition. NPredicateBuilder turns multiple LINQ Where and OrderBy methods into a single method call that makes your queries far more compact and easier to read. A base package allows to you run queries against LINQ-to-Objects, and a separate package allows you to run queries against Entity Framework. These packages have been split because the later has a dependency on EF.

Why NPredicateBuilder?

You can turn this:

            var results = people
                .Where(x => x.Name != "Joe")
                .Where(x => x.Age >= 10)
                .Where(x => x.IsEligible)
                .OrderBy(x => x.Name)
                .ThenBy(x => x.Age)
                .ToList();

into this...

          var query = new PersonQueries
                .IsNotNamedJoe()
                .IsOlderThan(10)
                .IsEligible();

          var order = new PersonOrders
                .ByName()
                .ThenByAge();

          var predicateBuilder = people
                .NPredicateBuilderWhere(query)
                .NPredicateBuilderOrder(order)
                .ToList();

Queries and Orders are Declarative

Your queries are far more descriptive and easier to read with NPredicateBuilder. Being forced to name a method "NameIsNotJoeAndIsOlderThanTenAndIsEligigleOrderedByNameThenAge" is pure insanity. NPredicateBuilder is declarative by nature. Your queries and orders describe themselves in a clear and concise fashion.

Everything is Now Testable

It is near impossible to test EF queries because the DbContext object is almost impossible to mock. The only way around this is to extract every predicate in your application so you can test it individually. NPredicateBuilder performs this behavior by default. Because every single Where and Order clause is separate, testing is easy.

The following demonstrates how to test an Order:

[TestMethod]
public void ByName_OrdersCorrectly()
{
    var bob = new Person { Name = "Bob" };
    var billy = new Person { Name = "Billy" };

    var people = new List<Person>
    {
        bob, billy
    };

    _order = new PersonOrders().ByName();

    var result = people
        .AsQueryable()
        .NPredicateBuilderOrder(_order).ToList();

    Assert.AreEqual(billy, result.First());
}

Removes Redundant Data Access Code

You may have seen interfaces littered with methods like this...

public interface IPersonRepository
{
    List<People> GetByName(string name);
    List<People> GetByNameAndAge(string name, int age);
    List<People> GetByStatusOrAddress(Status status, int zipcode);
    
    // There are probably many more methods in this interface all like the ones above.
}

With NPredicateBuilder, the above can become simply...

public interface IPersonRepository
{
    List<People> Search(BaseQuery<Person> query, BaseOrder<Person> order);
}

It Plays Nicely with Everything

Because NPredicateBuilder has two extension methods, you can plug it into any LINQ expression.

var predicateBuilder = people
            .NPredicateBuilderWhere(query)
            .NPredicateBuilderOrder(order)
            .GroupBy(x => x.Name)
            .Skip(10)
            .Take(100)
            .ToList();

Simplicity

NPredicateBuilder is dead simple. There are two bases classes, and two extensions methods to use. That's it.

Dependencies

NPredicateBuilder has a single dependency on LinqKit. This is used to expand the Expressions into a form that LINQ-To-Entities can translate to the correct SQL. To learn more about LinqKit, you can visit their GitHub page here.

Installation

Install-Package NPredicateBuilder -Version 4.0.0
Install-Package NPredicateBuilder.EF -Version 4.0.0