Skip to content

Repository files navigation

DynamicFilter

Nuget

DynamicFilter allows to use essential linq filtering methods in web api apps.

All operations were tested against EF Core and PostgreSql.

Usage

Model:

classProduct{publicGuidId{get;set;}publicstringName{get;set;}publicdecimalPrice{get;set;}publicboolIsInStock{get;set;}publicboolIsForSale{get;set;}publicDateTimeExpireDate{get;set;}}

Controller:

[Route("[controller]")]publicclassProductsController:ControllerBase{privatereadonlyAppDbContext_dbcontext;publicProductsController(AppDbContextdbcontext){_dbcontext=dbcontext;}[HttpPost("filter")]publicIActionResultGetFiltered([FromBody]Operation[]filter){returnOk(_dbcontext.Set<Product>().ApplyDynamicFilter(filter));}}

Filter:

[
{
"name": "where",
"arguments": {
"conditions": [
{
"field": "Name",
"operator": "Contains",
"value": ["Snickers"]
},
{
"logic": "And",
"field": "IsForSale",
"operator": "Equals",
"value": ["true"]
}
],
"groups": []
}
},
{
"name": "distinct"
},
{
"name": "orderBy",
"arguments": "ExpireDate"
},
{
"name": "orderByDescending",
"arguments": "Price"
},
{
"name": "thenBy",
"arguments": "IsInStock"
},
{
"name": "thenByDescending",
"arguments": "IsForSale"
},
{
"name": "skip",
"arguments": 1
},
{
"name": "take",
"arguments": 2
},
{
"name": "select",
"arguments": ["Id", "Name"]
}
]

Under the hood filter transforms into call

_dbcontext.Set<Product>().Where(x =>x.Name.Contains("Snickers")&&x.IsForSale).Distinct().OrderBy(x =>x.ExpireDate).OrderByDescending(x =>x.Price).ThenBy(x =>x.IsInStock).ThenByDescending(x =>x.IsForSale).Skip(1).Take(2).Select(x =>newDictionary<string,object>(){{"Id",x.Id},{"Name",x.Name}});

Such implementation of Select was made due to the limitations of anonymous types and should be used as the last operation and only to reduce the final number of properties to be fetched from the database.

At this point following operators are available to use in Where predicate:

 Equals
NotEqual
Any
Greater
GreaterOrEqual
Less
LessOrEqual
Exists
NotExists
StartsWith
EndsWith
Contains
NotContains

Examples

Advanced filtering

.Where(x =>((x.Name.EndsWith("Mars")||["Snickers","Mars"].Contains(x.Name))&&x.ExpireDate>=DateTime.UtcNow)&&(x.IsForSale||x.IsInStock))
[
{
"name": "where",
"arguments": {
"conditions": [
{
"field": "Name",
"operator": "EndsWith",
"value": ["Mars"]
},
{
"logic": "Or",
"field": "Name",
"operator": "Any",
"value": ["Snickers", "Mars"]
},
{
"logic": "And",
"field": "ExpireDate",
"operator": "GreaterOrEqual",
"value": ["2023-02-13 17:56:19Z"]
},
{
"logic": "And",
"field": "IsForSale",
"operator": "Equals",
"value": ["true"]
},
{
"logic": "Or",
"field": "IsInStock",
"operator": "Equals",
"value": ["true"]
}
],
"groups": [
{
"start": 1,
"end": 2,
"level": 1
},
{
"start": 1,
"end": 3,
"level": 2
},
{
"start": 4,
"end": 5,
"level": 2
}
]
}
}
]

Fetching specific field values

.Select(x =>x.Price).Distinct().OrderBy(x =>x)
[
{
"name": "select",
"arguments": "Price"
},
{
"name": "distinct"
},
{
"name": "orderBy"
}
]

About

DynamicFilter allows to use essential linq filtering methods in web api apps

Topics

Resources

Stars

1 star

Watchers

1 watching

Forks

Used by

Contributors

Languages