Castle.DynamicLinqQueryBuilder 2.0.0

dotnet add package Castle.DynamicLinqQueryBuilder --version 2.0.0
                    
NuGet\Install-Package Castle.DynamicLinqQueryBuilder -Version 2.0.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="Castle.DynamicLinqQueryBuilder" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Castle.DynamicLinqQueryBuilder" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Castle.DynamicLinqQueryBuilder" />
                    
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 Castle.DynamicLinqQueryBuilder --version 2.0.0
                    
#r "nuget: Castle.DynamicLinqQueryBuilder, 2.0.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 Castle.DynamicLinqQueryBuilder@2.0.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=Castle.DynamicLinqQueryBuilder&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Castle.DynamicLinqQueryBuilder&version=2.0.0
                    
Install as a Cake Tool

Dynamic Linq Query Builder

.NET Coverage Status Nuget

dynamic-linq-query-builder is a small library that allows any .NET collection to be filtered dynamically at runtime.

What's New in v2.0

Version 2.0 is a performance-focused release that targets .NET 8+ exclusively. By dropping support for legacy frameworks (.NET 4.5, .NET Standard 2.0, .NET 6), we were able to leverage modern .NET APIs that simply weren't available before:

  • FrozenDictionary for faster operator dispatch
  • Native System.DateOnly instead of a custom workaround
  • Modern caching primitives for expression and reflection caching

The result is a faster, leaner library with new opt-in features for scenarios where performance really matters.

Still on an older framework? Version 1.3.4 remains available on NuGet and continues to support .NET 4.5, .NET Standard 2.0, .NET 6, and .NET 8.

Features

  • Generates an IQueryable from any collection and filter combination
  • Capable of complex, grouped queries against as many fields as you want
  • Supports nested objects and collections via dot notation
  • Supports ORMs like EF6, EF Core, and MongoDB Client >=2.19
  • Compatible with jQuery QueryBuilder (see samples for an example)
  • Supports a number of operators for each type:
    • in
    • not in
    • equal
    • not equal
    • between
    • not between
    • less
    • less or equal
    • greater
    • greater or equal
    • begins with
    • not begins with
    • contains
    • not contains
    • ends with
    • not ends with
    • is empty
    • is not empty
    • is null
    • is not null
    • custom operators via IFilterOperator interface and options

New in v2.0

  • Expression & predicate caching — opt-in caching for repeated queries (up to 150x faster)
  • Optimized string comparison — opt-in StringComparison.OrdinalIgnoreCase mode for in-memory scenarios
  • HashSet optimization — automatic O(1) lookups for large in operations
  • Reduced allocations — internal caching of reflection lookups and static lambdas

Performance at a Glance

Scenario v1.3.4 v2.0 Improvement
Large in (500 values) 3,525 μs 421 μs 88% faster
Repeated queries (cached) 210 μs 1.4 μs 150x faster
String filter (ordinal mode) 490 μs 309 μs 37% faster, 85% less memory

Quick Start: New v2.0 Options

All new features are opt-in — your existing code works without changes.

Expression Caching

If you're running the same filter structure repeatedly (e.g., in a loop or API endpoint), enable caching to skip redundant expression building:

var options = new BuildExpressionOptions 
{ 
    EnableExpressionCaching = true,  // Cache built expression trees
    EnablePredicateCaching = true    // Cache compiled delegates
};

// First call builds and caches; subsequent calls are ~150x faster
var results = myCollection.BuildQuery(filter, options).ToList();

Optimized String Comparison

For in-memory scenarios (not EF Core or other ORMs), enable ordinal string comparison to avoid ToLower() allocations:

var options = new BuildExpressionOptions 
{ 
    UseOrdinalStringComparison = true  // Uses StringComparison.OrdinalIgnoreCase
};

var results = myCollection.BuildQuery(filter, options).ToList();

Note: Keep this false (default) when using with EF Core, EF6, or other ORMs that translate expressions to SQL. The ToLower() approach is required for database compatibility.

Installation

Install via NuGet UI or Package Manager Console:

PM> Install-Package Castle.DynamicLinqQueryBuilder

For System.Text.Json support:

PM> Install-Package Castle.DynamicLinqQueryBuilder.SystemTextJson

Targets: .NET 8+

Upgrading from v1.x

Migrating to v2.0 is straightforward:

  1. Update your target framework to net8.0 or later
  2. Update the NuGet package to v2.0
  3. That's it! All new options are opt-in; existing code works unchanged

If you can't upgrade to .NET 8, stay on v1.3.4 — it's still fully functional and available on NuGet.

Getting Started

The easiest way to get started is to install the NuGet package and take a look at the MVC sample application included in the source code. It contains a working example of both dynamic-linq-query-builder and jQuery-QueryBuilder.

For more details, see the Wiki.

Contributions

Contributions and pull requests are welcome with associated unit tests.

Product Compatible and additional computed target framework versions.
.NET 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 was computed.  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 was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages (5)

Showing the top 5 NuGet packages that depend on Castle.DynamicLinqQueryBuilder:

Package Downloads
Castle.DynamicLinqQueryBuilder.SystemTextJson

A companion package for those using System.Text.Json

MSFactory.ToolKits

Package Description

Iu5dmf.Sphere.Gui.Core

GUI Core library for Sphere

CPIT.DynamicForm

Package Description

DataModeler

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
2.0.0 97 1/21/2026
1.3.4 113,584 8/31/2024
1.3.3 153,157 8/30/2023
1.3.2 26,685 5/2/2023
1.3.1 772 4/29/2023
1.3.0 3,656 4/20/2023
1.2.9 61,540 10/8/2022
1.2.8 1,121 10/6/2022
1.2.7 3,928 9/13/2022
1.2.6 15,934 8/7/2022
1.2.5 357,953 5/3/2022
1.2.4 29,692 3/7/2022
1.2.3 136,200 12/2/2021
1.2.2 5,083 11/20/2021
1.2.1 1,065 11/18/2021
1.2.0 74,813 12/3/2020
1.1.4 154,364 6/15/2019
1.1.3 7,833 3/27/2019
1.1.2 2,947 2/17/2019
1.1.1 3,025 1/12/2019
1.1.0 1,578 12/25/2018
1.0.5 72,721 7/2/2016
1.0.5-prerelease 2,559 3/9/2016
1.0.4 2,052 3/4/2016
1.0.3 1,863 3/1/2016
1.0.2 1,977 2/23/2016
1.0.1 2,019 1/27/2016

v2.0.0 - Major performance improvements, .NET 8 only