-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
88 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,89 @@ | ||
# DynamicExpressions | ||
A dynamic expression builder that can be used to dynamically sort and/or filter LINQ/EF queries | ||
|
||
A dynamic expression builder that can be used to dynamically sort and/or filter LINQ/EF queries. | ||
I wrote a blog post that explains the usage & benefits, check it out [here](https://blog.zhaytam.com/2020/05/17/dynamic-sorting-filtering-csharp/). | ||
|
||
This library tries to generate Expression Trees as close to the one generated by c# as possible, so in almost all cases, you don't even need to worry about performance. | ||
|
||
||Badges| | ||
|--|--| | ||
|NuGet|[](https://www.nuget.org/packages/DynamicExpressions.NET) [](https://www.nuget.org/packages/DynamicExpressions.NET)| | ||
|License|[](https://github.com/zHaytam/DynamicExpressions)| | ||
|
||
## Property Getters | ||
|
||
This is usually used when you want to do an `OrderBy` or `OrderByDescending`. | ||
For example: | ||
|
||
```cs | ||
_dbContext.Products.AsQueryable().OrderBy(p => p.Price); | ||
``` | ||
|
||
If you want to give the ability for the user to choose what to order by, you'll need to do a switch statement with all the possible values, which can be exhausting, especially if it's for multiple entities. | ||
|
||
Using this library, you can simply do this: | ||
|
||
```cs | ||
var propertyGetter = DynamicExpressions.GetPropertyGetter<Product>(propertySentByUser); | ||
// ^ can be cached or even compiled to a Func<Product, object> | ||
var query = _dbContext.Products.AsQueryable().OrderBy(propertyGetter); | ||
// Or OrderByDesceding | ||
``` | ||
|
||
And it will handle all the properties, unless you do a pre-validation. | ||
|
||
## Predicates | ||
|
||
### Simple | ||
|
||
Predicates in c# are functions that take one or more parameter and returns a boolean. | ||
For example, when you want to filter an `IQueryable`, you use a `Func<TEntity, bool>`. | ||
|
||
For example: | ||
```cs | ||
_dbContext.Products.AsQueryable().Where(p => p.Name.Contains(termSentByUser)); | ||
``` | ||
|
||
Again, this only handles a `Contains` filter on the `Name` property. | ||
The more properties and operators you have, the more "boring" code you'll need to write. | ||
|
||
Using this library, you can simple do this: | ||
|
||
```cs | ||
var predicate = DynamicExpressions.GetPredicate<Product>(propertySentByUser, operatorSentByUser, valueSentByUser); | ||
// ^ can also be cached or compiled and used anywhere | ||
var products = _dbContext.Products.AsQueryable().Where(predicate).ToList(); | ||
// ^ or FirstByDefault, Any, etc... | ||
``` | ||
|
||
### Advanced | ||
|
||
In the previous example, we filtered products only on their price. We will now see how we can create advnaced dynamic predicates. | ||
|
||
Let's say for example you want to create the following filter: | ||
|
||
```cs | ||
Product.Enabled | ||
&& (Product.Brand == "Nike" || Product.Brand == "Adidas") | ||
&& (Product.Price >= 20 && Product.Price <= 100) | ||
``` | ||
|
||
Using this library, you're able to do this: | ||
|
||
```cs | ||
var predicate = new DynamicFilterBuilder<Product>() | ||
.And("Enabled", FilterOperator.Equals, true) | ||
.And(b => b.And("Brand", FilterOperator.Equals, "Nike").Or("Brand", FilterOperator.Equals, "Adidas")) | ||
.And(b => b.And("Price", FilterOperator.GreaterThanOrEqual, 20).And("Price", FilterOperator.LessThanOrEqual, 100)) | ||
.Build(); | ||
|
||
var products = _dbContext.Products.AsQueryable().Where(predicate).ToList(); | ||
``` | ||
|
||
Of course, everything can be configurable and provided by the user. | ||
A more real life example would be for the frontend (user) to give you a list of filters that you can dynamically apply using a `DynamicFilterBuilder`. | ||
|
||
## Feedback | ||
|
||
If you find a bug or you want to see a functionality in this library, feel free to open an issue in the repository! | ||
Of course, PRs are very welcome. |