DynamicQueryable.Extensions 2.0.0

Suggested Alternatives

FlexQuery.NET

Additional Details

This package has been deprecated. Please use FlexQuery.NET instead:
FlexQuery.NET

There is a newer version of this package available.
See the version list below for details.
dotnet add package DynamicQueryable.Extensions --version 2.0.0
                    
NuGet\Install-Package DynamicQueryable.Extensions -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="DynamicQueryable.Extensions" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="DynamicQueryable.Extensions" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="DynamicQueryable.Extensions" />
                    
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 DynamicQueryable.Extensions --version 2.0.0
                    
#r "nuget: DynamicQueryable.Extensions, 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 DynamicQueryable.Extensions@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=DynamicQueryable.Extensions&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=DynamicQueryable.Extensions&version=2.0.0
                    
Install as a Cake Tool

๐Ÿš€ DynamicQueryable

DynamicQueryable is a lightweight, extensible .NET 8 library that enables dynamic filtering, sorting, pagination, and projection for IQueryable.

It supports multiple query formats (Generic, JSON, Syncfusion, Laravel Spatie) and is designed to integrate seamlessly with Entity Framework Core or any LINQ provider.


  • โœ… Dynamic filtering (OData-lite style)
  • โœ… Sorting (multi-field)
  • โœ… Pagination (skip/take)
  • โœ… Projection (select with nested properties)
  • โœ… Include support (nested property projection)
  • โœ… Query parameter parser
    • Generic format
    • JSON format
    • Syncfusion
    • Laravel Spatie
  • โœ… Fully testable and extensible

๐Ÿ“ฆ Installation

dotnet add package DynamicQueryable.Extensions

โšก Quick Start

1. Parse Query Options

Use the QueryOptionsParser to convert your query string parameters into a QueryOptions object.

using DynamicQueryable.Parsers;

// In a controller or minimal API:
var options = QueryOptionsParser.Parse(Request.Query);

2. Apply to IQueryable

Use the extension methods provided in DynamicQueryable.Extensions.

using DynamicQueryable.Extensions;

[HttpGet]
public async Task<IActionResult> Get()
{
    var options = QueryOptionsParser.Parse(Request.Query);
    
    // Simple usage (returns paged data)
    var users = await _context.Users
        .ApplyQueryOptions(options)
        .ToListAsync();

    // Or use ToQueryResult for metadata (TotalCount, Page, etc.)
    var result = _context.Users.ToQueryResult(options);
    
    return Ok(result);
}

๐Ÿ” Query Examples

โœ… Filtering

?filter[0].field=Name
&filter[0].operator=contains
&filter[0].value=john

โœ… Sorting

?sort[0].field=Age
&sort[0].desc=true

โœ… Pagination

?page=1&pageSize=10

โœ… Projection

?select=Id,Name,Email

โœ… Nested Projection

?select=Id,Name,Profile.Name,Orders.Total

โœ… Include + Select

?include=Profile,Orders
&select=Id,Name,Profile.Name,Orders.Total

๐Ÿ”ง Supported Operators

Operator Description Example
eq Equal Name eq 'John'
neq Not equal Age neq 30
gt Greater than Age gt 18
gte Greater than or equal Age gte 18
lt Less than Age lt 60
lte Less than or equal Age lte 60
contains String contains Name contains 'jo'
startswith String starts with Name startswith 'Jo'
endswith String ends with Name endswith 'hn'
in Value exists in a list Status in ['Active','Pending']
isnull Check if value is null DeletedAt isnull true

๐Ÿ” Operator Examples

Basic
?filter[0].field=Name
&filter[0].operator=eq
&filter[0].value=John
Contains
?filter[0].field=Name
&filter[0].operator=contains
&filter[0].value=jo
Range
?filter[0].field=Age
&filter[0].operator=gte
&filter[0].value=18
&filter[1].field=Age
&filter[1].operator=lte
&filter[1].value=60
IN
?filter[0].field=Status
&filter[0].operator=in
&filter[0].value=Active,Pending
NULL
?filter[0].field=DeletedAt
&filter[0].operator=isnull
&filter[0].value=true

๐Ÿ”„ Supported Query Formats

๐Ÿ”น Generic

?filter[0].field=Name
&filter[0].operator=contains
&filter[0].value=john

๐Ÿ”น JSON

?filter={
  "logic":"and",
  "filters":[
    {"field":"Name","operator":"contains","value":"john"}
  ]
}

๐Ÿ”น Syncfusion

?where[0][field]=Name
&where[0][operator]=contains
&where[0][value]=john
&sorted[0][name]=Age
&sorted[0][direction]=descending
&skip=0
&take=10

๐Ÿ”น Laravel Spatie

?filter[name]=john
&filter[age]=25
&sort=-created_at
&include=roles,permissions
&fields[users]=name,email

๐Ÿงฉ Projection System

Supports:

  • Root fields
  • Nested objects
  • Collections

Example:

?select=Id,Name,Profile.Name,Orders.Total

โš™๏ธ Usage Details

Manual Construction

You can also build QueryOptions manually in code:

var options = new QueryOptions
{
    Filter = new FilterGroup
    {
        Filters = [new FilterCondition { Field = "Age", Operator = "gt", Value = "18" }]
    },
    Sort = [new SortOption { Field = "Name", Descending = false }],
    Paging = new PagingOptions { Page = 1, PageSize = 10 }
};

var query = _context.Users.ApplyQueryOptions(options);

๐Ÿ”Œ ASP.NET Core Integration

Since the parser is static, you can easily wrap it in a custom ModelBinder or just call it directly in your base controller.

public abstract class BaseController : ControllerBase
{
    protected QueryOptions QueryOptions => QueryOptionsParser.Parse(Request.Query);
}

๐Ÿงช Testing

Run tests:

dotnet test

Includes:

  • Filtering
  • Sorting
  • Paging
  • Projection
  • Parser

๐Ÿงฑ Architecture

DynamicQueryable.Extensions
โ”‚
โ”œโ”€โ”€ Models      (FilterCondition, SortOption, etc.)
โ”œโ”€โ”€ Builders    (ExpressionBuilder, ProjectionBuilder)
โ”œโ”€โ”€ Extensions  (QueryableExtensions)
โ”œโ”€โ”€ Helpers     (SelectTreeBuilder)
โ””โ”€โ”€ Parsers     (QueryOptionsParser)

๐Ÿ”— Integration with BaseRepository

public async Task<QueryResult<T>> GetPagedAsync(QueryOptions options)
{
    return _dbSet.AsQueryable().ToQueryResult(options);
}

๐Ÿš€ Roadmap

  • Redis caching implementation
  • Expression caching (performance)
  • Field-level authorization
  • GraphQL-style query support

๐Ÿค Contributing

Contributions, issues, and feature requests are welcome.


๐Ÿ“„ License

MIT License

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.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.