Castle.DynamicLinqQueryBuilder
2.0.0
dotnet add package Castle.DynamicLinqQueryBuilder --version 2.0.0
NuGet\Install-Package Castle.DynamicLinqQueryBuilder -Version 2.0.0
<PackageReference Include="Castle.DynamicLinqQueryBuilder" Version="2.0.0" />
<PackageVersion Include="Castle.DynamicLinqQueryBuilder" Version="2.0.0" />
<PackageReference Include="Castle.DynamicLinqQueryBuilder" />
paket add Castle.DynamicLinqQueryBuilder --version 2.0.0
#r "nuget: Castle.DynamicLinqQueryBuilder, 2.0.0"
#:package Castle.DynamicLinqQueryBuilder@2.0.0
#addin nuget:?package=Castle.DynamicLinqQueryBuilder&version=2.0.0
#tool nuget:?package=Castle.DynamicLinqQueryBuilder&version=2.0.0
Dynamic Linq Query Builder
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:
FrozenDictionaryfor faster operator dispatch- Native
System.DateOnlyinstead 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
IQueryablefrom 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, andMongoDB 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
IFilterOperatorinterface 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.OrdinalIgnoreCasemode for in-memory scenarios - HashSet optimization — automatic O(1) lookups for large
inoperations - 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. TheToLower()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:
- Update your target framework to
net8.0or later - Update the NuGet package to v2.0
- 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 | Versions 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. |
-
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