LinqBuilder 4.1.0

dotnet add package LinqBuilder --version 4.1.0
                    
NuGet\Install-Package LinqBuilder -Version 4.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="LinqBuilder" Version="4.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="LinqBuilder" Version="4.1.0" />
                    
Directory.Packages.props
<PackageReference Include="LinqBuilder" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add LinqBuilder --version 4.1.0
                    
#r "nuget: LinqBuilder, 4.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package LinqBuilder@4.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=LinqBuilder&version=4.1.0
                    
Install as a Cake Addin
#tool nuget:?package=LinqBuilder&version=4.1.0
                    
Install as a Cake Tool

LinqBuilder

The specification pattern for LINQ. LinqBuilder lets you write a filter once, as a specification, combine it with other specifications, add ordering and paging, and run it on any IQueryable<T> or IEnumerable<T>. Specifications are expression trees, so Entity Framework Core, Entity Framework 6 and other LINQ providers translate them to SQL.

var spec = new IsAdult()
    .And(new LastNameIs("Smith"))
    .OrderBy(OrderSpec<Person, string>.New(p => p.FirstName))
    .Paginate(pageNo: 1, pageSize: 20);

List<Person> page = await db.People.ExeSpec(spec).ToListAsync();

Full documentation: github.com/Baune8D/LinqBuilder

Features

  • Reusable filters: write a specification as a class (Specification<T>) or inline from a lambda (Spec<T>.New(...)).
  • Parameters: DynamicSpecification<T, TValue> passes up to four values into the filter, e.g. new LastNameIs("Smith").
  • Composition: And, Or and Not, plus Spec<T>.All(...), Spec<T>.Any(...) and Spec<T>.None(...).
  • Ordering and paging: OrderBy, ThenBy, Skip, Take and Paginate are stored in the specification and applied by ExeSpec.
  • IQueryable<T> and IEnumerable<T>: a query gets the filter as an expression tree, an in-memory collection as a compiled delegate.
  • LINQ overloads: Where, Any, All, Count, First, FirstOrDefault, Single and SingleOrDefault take a specification.
  • In-memory checks: spec.IsSatisfiedBy(entity).
  • One specification for several entity types: MultiSpecification<T1, T2>, up to four types.
  • Targets .NET Standard 2.0 and .NET 8, 9 and 10.

For async Entity Framework methods that take a specification (AnyAsync, CountAsync, FirstOrDefaultAsync, ...), install LinqBuilder.EFCore or LinqBuilder.EF6 instead. Both depend on this package.

Getting started

1. Install

dotnet add package LinqBuilder

2. Write specifications

The examples use this entity:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; } = "";
    public string LastName { get; set; } = "";
    public int Age { get; set; }
    public bool IsActive { get; set; }
}

A specification returns its filter from AsExpression():

using System;
using System.Linq.Expressions;
using LinqBuilder;

public class IsAdult : Specification<Person>
{
    public override Expression<Func<Person, bool>> AsExpression()
    {
        return person => person.Age >= 18;
    }
}

public class LastNameIs : DynamicSpecification<Person, string>
{
    public LastNameIs(string lastName)
        : base(lastName)
    {
    }

    public override Expression<Func<Person, bool>> AsExpression()
    {
        return person => person.LastName == Value;
    }
}

For a one-off filter you don't need a class: Spec<Person>.New(p => p.IsActive).

3. Combine and run them

using LinqBuilder;
using LinqBuilder.OrderBy;

ISpecification<Person> spec = new IsAdult()
    .And(new LastNameIs("Smith"))
    .OrderBy(OrderSpec<Person, string>.New(p => p.FirstName))
    .Paginate(pageNo: 2, pageSize: 10);

List<Person> page = people.ExeSpec(spec).ToList(); // filter, sort, skip 10, take 10
int total = people.Count(spec);                    // filter only: all adults named Smith

people can be any IEnumerable<Person> or IQueryable<Person>, such as a List<Person> or an EF Core DbSet<Person>.

Methods

Creating and combining specifications

Namespace LinqBuilder.

Method Description
Spec<T>.New(expression) A specification from a lambda. Spec<T> is an alias of Specification<T>.
Spec<T>.New() An empty specification. It matches every entity and is ignored by And and Or.
a.And(b), a.Or(b), a.Not() Combine filters. The result keeps the ordering, Skip and Take of a.
Spec<T>.All(a, b, ...) Matches entities that match all of them.
Spec<T>.Any(a, b, ...) Matches entities that match at least one of them.
Spec<T>.None(a, b, ...) Same as Spec<T>.Any(a, b, ...).Not(): matches entities that match none of them.

All, Any and None keep only the filters of their arguments. See Specifications for dynamic (DynamicSpecification) and multi-entity (MultiSpecification) specifications.

Ordering and paging

Namespace LinqBuilder.OrderBy.

Method Description
OrderSpec<T, TResult>.New(keySelector, sort) An order specification (one sort key). sort is Sort.Ascending (the default) or Sort.Descending. OrderSpec is an alias of OrderSpecification.
spec.OrderBy(order) Adds order as a sort key. Returns an IOrderedSpecification<T>.
ordered.ThenBy(order) Adds another sort key, on the result of OrderBy or ThenBy, or on an order specification.
spec.UseOrdering(other) A copy of spec with the sort keys of other added. Skip and Take come from other when it sets them, otherwise from spec.
spec.Skip(count), spec.Take(count) Set the number of entities to skip and the maximum number to return. Calling them again replaces the value.
spec.Paginate(pageNo, pageSize) Skip((pageNo - 1) * pageSize) and Take(pageSize). pageNo starts at 1.
spec.IsOrdered(), spec.HasSkip(), spec.HasTake() Check whether a specification has sort keys, a Skip or a Take.

Running specifications

Namespace LinqBuilder.

Method Description
source.ExeSpec(spec) Applies the filter, sort keys, Skip and Take, in that order. Returns an IQueryable<T> for a query and an IEnumerable<T> for a collection.
source.ExeSpec(spec, skipSort: true) Applies only the filter.
Where, Any, All, Count, First, FirstOrDefault, Single, SingleOrDefault LINQ overloads that take a specification, on IQueryable<T> and IEnumerable<T>. They use only the filter and ignore the sort keys, Skip and Take.
spec.IsSatisfiedBy(entity) Runs the filter on one entity.
spec.Clone() A new specification with the same filter, sort keys, Skip and Take.

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on LinqBuilder:

Package Downloads
LinqBuilder.EFCore

Entity Framework Core extensions. Enables most async methods to use ISpecification.

LinqBuilder.EF6

Entity Framework 6 extensions. Enables most async methods to use ISpecification.

LinqBuilder.EF6.AutoMapper

Extensions for querying EF 6 with AutoMapper projections.

LinqBuilder.EFCore.AutoMapper

Extensions for querying EF Core with AutoMapper projections.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
4.1.0 58 11/2/2026
4.0.0 1,693 1/8/2026
3.2.0 13,840 12/30/2024
3.1.0 14,489 5/5/2024
3.0.1 18,083 10/18/2023
3.0.0 363 10/17/2023
2.1.2 44,837 4/14/2022
2.1.1 1,107 4/13/2022
2.1.0 1,096 4/13/2022
2.0.0 1,856 1/19/2021
1.0.1 8,913 11/3/2020
1.0.0 1,119 11/3/2020
0.16.1 54,327 8/29/2019
0.15.0 4,822 12/4/2018
0.14.0 1,029 12/3/2018
0.13.0 4,752 9/17/2018
0.12.1 1,797 7/18/2018
0.12.0 1,283 7/18/2018
0.11.1 1,286 7/18/2018
0.11.0 1,791 6/24/2018
Loading failed