![]() |
VOOZH | about |
dotnet add package AlJawad.SqlDynamicLinker --version 1.0.9
NuGet\Install-Package AlJawad.SqlDynamicLinker -Version 1.0.9
<PackageReference Include="AlJawad.SqlDynamicLinker" Version="1.0.9" />
<PackageVersion Include="AlJawad.SqlDynamicLinker" Version="1.0.9" />Directory.Packages.props
<PackageReference Include="AlJawad.SqlDynamicLinker" />Project file
paket add AlJawad.SqlDynamicLinker --version 1.0.9
#r "nuget: AlJawad.SqlDynamicLinker, 1.0.9"
#:package AlJawad.SqlDynamicLinker@1.0.9
#addin nuget:?package=AlJawad.SqlDynamicLinker&version=1.0.9Install as a Cake Addin
#tool nuget:?package=AlJawad.SqlDynamicLinker&version=1.0.9Install as a Cake Tool
AlJawad.SqlDynamicLinker is a .NET library that empowers developers to build dynamic, client-driven queries for Entity Framework Core. It allows frontend applications to specify filtering, sorting, and related-entity inclusion (eager loading) through a flexible JSON structure, which is then translated into efficient IQueryable expressions.
This library is perfect for building APIs that need to support complex data grids, search pages, or any scenario where the client needs to control the data shaping.
.Filter() , .Includes() and .Sort() extension method is all you need to apply the dynamic query.You can install the package via NuGet Package Manager or the .NET CLI.
dotnet add package AlJawad.SqlDynamicLinker
Install-Package AlJawad.SqlDynamicLinker
Program.csTo use AlJawad.SqlDynamicLinker, you need to configure services in your Program.cs (or Startup.cs).
[FromBody])If you are passing the filter object in the request body (e.g., in a POST request), you need to add the custom JsonConverter:
using AlJawad.SqlDynamicLinker.Converters;
using AlJawad.SqlDynamicLinker.ModelBinder;
builder.Services
.AddNewtonsoftJson(options =>
{
options.SerializerSettings.Converters.Add(new EntityBaseFilterConverter());
});
[FromQuery])If you are passing the filter parameters in the query string (e.g., in a GET request), you need to add the custom ModelBinderProviders:
using AlJawad.SqlDynamicLinker.ModelBinder;
builder.Services.AddControllers(options =>
{
options.ModelBinderProviders.Add(new BaseQueryableFilterBinderProvider());
options.ModelBinderProviders.Add(new BasePagingFilterBinderProvider());
});
You may need to add both configurations if you plan to support both scenarios.
In your API controller, you can now accept a BaseQueryableFilter object in your action methods, either from the request body ([FromBody]) or from the query string ([FromQuery]), depending on your configuration.
Here's an example of a controller that uses the library to filter a list of products:
using AlJawad.SqlDynamicLinker.DynamicFilter;
using AlJawad.SqlDynamicLinker.Extensions;
using Microsoft.AspNetCore.Mvc;
[Route("api/[controller]")]
[ApiController]
public class ProductController : ControllerBase
{
private readonly IQueryable<Product> _products; // Your IQueryable source
public ProductController(YourDbContext dbContext)
{
_products = dbContext.Products;
}
[HttpPost("search")]
public IActionResult SearchProducts([FromBody] BaseQueryableFilter filter)
{
var filteredProducts = _products.Filter(filter);
return Ok(filteredProducts.ToList());
}
}
BaseQueryableFilter ObjectThe BaseQueryableFilter is the main object that you'll use to define your queries. It has the following properties:
DynamicFilters (array): An array of filter objects.DynamicSorting (array): An array of sorting objects.IncludeProperties (array): An array of objects to specify which related entities to include.Here is a full example of a BaseQueryableFilter object:
{
"IncludeProperties": [
{ "dataName": "MainCategory" },
{ "dataName": "ProductCategories.Category" }
],
"DynamicFilters": [
{
"logic": "and",
"dataName": "Name",
"operator": "Contains",
"value": "phone"
},
{
"logic": "and",
"dataName": "Price",
"operator": "gte",
"value": 100
}
],
"DynamicSorting": [
{
"sortIndex": 0,
"dataName": "Price",
"IsAscending": false
}
]
}
The DynamicFilters array contains one or more filter objects. Each object defines a condition to apply to the query.
A simple filter object has the following properties:
logic (string): The logical operator to use when combining this filter with the previous one. Can be "and" or "or". The first filter's logic is ignored.dataName (string): The name of the property to filter on. You can use dot notation for nested properties (e.g., "MainCategory.Name").operator (string): The comparison operator. See the list of supported operators below.value (any): The value to compare against.Example: Find all products with the name "Laptop"
{
"DynamicFilters": [
{
"dataName": "Name",
"operator": "eq",
"value": "Laptop"
}
]
}
| Operator | Description |
|---|---|
eq |
Equal |
neq |
Not Equal |
gt |
Greater Than |
gte |
Greater Than or Equal |
lt |
Less Than |
lte |
Less Than or Equal |
StartsWith |
The string starts with the value |
EndsWith |
The string ends with the value |
Contains |
The string contains the value |
The library supports filtering based on geographic location. A geometry filter object has the following properties:
DataName (string): The name of the property that stores the geometry data (must be a Point type in the database).Operator (string): Must be "within".Latitude (number): The latitude of the center of the circle.Longitude (number): The longitude of the center of the circle.Radius (number): The radius of the circle in meters.Example: Find all stores within a 1500-meter radius of a point
{
"DynamicFilters": [
{
"DataName": "Location",
"Operator": "within",
"Latitude": 34.0522,
"Longitude": -118.2437,
"Radius": 1500
}
]
}
The DynamicSorting array allows you to sort the results by one or more fields. Each sorting object has the following properties:
sortIndex (number): The order in which to apply the sorting.dataName (string): The name of the property to sort by.IsAscending (boolean): true for ascending order, false for descending.The sort also support json structure but you have to pay attention for the performance (use indexing if needed)
Example: Sort products by price (descending) and then by name (ascending)
{
"DynamicSorting": [
{
"sortIndex": 0,
"dataName": "Price",
"IsAscending": false
},
{
"sortIndex": 1,
"dataName": "Name",
"IsAscending": true
}
]
}
The IncludeProperties array allows you to specify which related entities to eager load. This is equivalent to using .Include() in Entity Framework. Each object in the array has one property:
dataName (string): The name of the navigation property to include. You can use dot notation for nested includes (e.g., "Order.OrderItems").Example: Include the main category and the product's categories
{
"IncludeProperties": [
{ "dataName": "MainCategory" },
{ "dataName": "ProductCategories.Category" }
]
}
This project is licensed under the MIT License. See the file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 2 NuGet packages that depend on AlJawad.SqlDynamicLinker:
| Package | Downloads |
|---|---|
|
AlJawad.DefaultCQRS
A powerful and scalable CQRS library for .NET applications. |
|
|
AlJawad.BaseRAG
AlJawad.BaseRAG |
This package is not used by any popular GitHub repositories.