DynamicQueryable.Extensions
2.0.0
This package has been deprecated. Please use FlexQuery.NET instead:
FlexQuery.NET
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
<PackageReference Include="DynamicQueryable.Extensions" Version="2.0.0" />
<PackageVersion Include="DynamicQueryable.Extensions" Version="2.0.0" />
<PackageReference Include="DynamicQueryable.Extensions" />
paket add DynamicQueryable.Extensions --version 2.0.0
#r "nuget: DynamicQueryable.Extensions, 2.0.0"
#:package DynamicQueryable.Extensions@2.0.0
#addin nuget:?package=DynamicQueryable.Extensions&version=2.0.0
#tool nuget:?package=DynamicQueryable.Extensions&version=2.0.0
๐ 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 (
selectwith 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 | 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
- Microsoft.Extensions.Primitives (>= 8.0.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated | |
|---|---|---|---|
| 2.5.0 | 173 | 5/1/2026 | |
| 2.4.0 | 115 | 5/1/2026 | |
| 2.3.0 | 110 | 5/1/2026 | |
| 2.2.1 | 107 | 5/1/2026 | |
| 2.2.0 | 112 | 5/1/2026 | |
| 2.1.0 | 104 | 4/30/2026 | |
| 2.0.1 | 111 | 4/30/2026 | |
| 2.0.0 | 107 | 4/30/2026 | |
| 1.9.0 | 112 | 4/30/2026 | |
| 1.8.0 | 139 | 4/30/2026 | |
| 1.7.0 | 111 | 4/29/2026 | |
| 1.6.4 | 117 | 4/29/2026 | |
| 1.6.2 | 107 | 4/29/2026 | |
| 1.6.1 | 102 | 4/29/2026 | |
| 1.6.0 | 111 | 4/29/2026 | |
| 1.5.0 | 114 | 4/29/2026 |