Skip to content

A truly generic and dynamic linq query builder to compliment jQuery QueryBuilder and other dynamic linq query generation needs

License

Notifications You must be signed in to change notification settings

tghamm/dynamic-linq-query-builder

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

255 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

A truly generic and dynamic linq query builder to compliment jQuery QueryBuilder and other dynamic linq query generation needs

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 17

Languages