ART4S.Autofilter
3.0.0
dotnet add package ART4S.Autofilter --version 3.0.0
NuGet\Install-Package ART4S.Autofilter -Version 3.0.0
<PackageReference Include="ART4S.Autofilter" Version="3.0.0" />
paket add ART4S.Autofilter --version 3.0.0
#r "nuget: ART4S.Autofilter, 3.0.0"
// Install ART4S.Autofilter as a Cake Addin
#addin nuget:?package=ART4S.Autofilter&version=3.0.0
// Install ART4S.Autofilter as a Cake Tool
#tool nuget:?package=ART4S.Autofilter&version=3.0.0
Autofilter
Autofilter simplifies data filtering using Expression Trees. Reduces amount of code needed for manual writing filtering logic on backend side.
Inspired by Max Arshinov's article.
All operations were tested against EF Core and PostgreSql.
Any issues or criticism are welcome 😃
Introduction
Create a model
class Product
{
public Guid Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public bool IsInStock { get; set; }
public bool IsForSale { get; set; }
public DateTime ExpireDate { get; set; }
}
Build a filter
var filter = new AutoFilter
(
Filter: new FilterRule
(
Conditions: new[]
{
new Condition
(
Name: "Name",
SearchOperator: SearchOperator.Contains,
Value: new[]{ "Snickers" }
),
new Condition
(
LogicOperator: LogicOperator.And,
Name: "IsForSale",
SearchOperator: SearchOperator.Equals,
Value: new[] { "true" }
),
}
)
);
Apply filter to queryable
queryable.ApplyFilter(filter);
Under the hood filter transforms into call
queryable.Where(x => x.Name.Contains("Snickers") && x.IsForSale);
Examples
Filtering
queryable.Where(x => ((x.Name.StartsWith("Snickers") || x.Name.Contains("Mars")) && x.ExpireDate >= DateTime.UtcNow) && (x.IsForSale || x.IsInStock))
var filter = new AutoFilter
(
Filter: new FilterRule
(
new Condition[]
{
new
(
Name: nameof(Product.Name),
SearchOperator: SearchOperator.StartsWith,
Value: new[]{ "Snickers" }
),
new
(
LogicOperator: LogicOperator.Or,
Name: nameof(Product.Name),
SearchOperator: SearchOperator.Contains,
Value: new[]{ "Mars" }
),
new
(
LogicOperator: LogicOperator.And,
Name: nameof(Product.ExpireDate),
SearchOperator: SearchOperator.GreaterOrEqual,
Value: new[] { DateTime.UtcNow.ToString("u") }
),
new
(
LogicOperator: LogicOperator.And,
Name: nameof(Product.IsForSale),
SearchOperator: SearchOperator.Equals,
Value: new[] { "true" }
),
new
(
LogicOperator: LogicOperator.Or,
Name: nameof(Product.IsInStock),
SearchOperator: SearchOperator.Equals,
Value: new[] { "true" }
),
},
new Group[]
{
new
(
Start: 1,
End: 2,
Level: 1
),
new
(
Start: 1,
End: 3,
Level: 2
),
new
(
Start: 4,
End: 5,
Level: 2
)
}
)
);
queryable.ApplyFilter(filter);
Distinct
queryable.Distinct();
var filter = new AutoFilter
(
DistinctBy: ""
);
queryable.ApplyFilter(filter);
queryable.DistinctBy(x => x.Name);
var filter = new AutoFilter
(
DistinctBy: "Name"
);
queryable.ApplyFilter(filter);
Sorting
queryable.OrderBy(x => x.ExpireDate);
var filter = new AutoFilter
(
Sorting: new SortingRule
(
PropertyName: "ExpireDate"
)
);
queryable.ApplyFilter(filter);
queryable.OrderBy(x => x.ExpireDate).ThenByDescending(x => x.Price);
var filters = new AutoFilter[]
{
new
(
Sorting: new SortingRule
(
PropertyName: "ExpireDate"
)
),
new
(
Sorting: new SortingRule
(
PropertyName: "Price",
ThenBy: true,
IsDescending: true
)
),
};
queryable.ApplyFilters(filters);
Paging
queryable.Skip(5).Take(1);
var filters = new[]
{
new AutoFilter(Skip: 5),
new AutoFilter(Top: 1)
};
queryable.ApplyFilters(filters);
Select
queryable.Select(x => new Dictionary<string, object>()
{
{ "Id", x.Id },
{ "Name", x.Name }
})
var filter = new AutoFilter
(
Select: new[] { "Id", "Name" }
);
queryable.ApplyFilterAndSelect(filter);
This 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.
Operations vs Types compatibility
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
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 |
---|---|---|
3.0.0 | 291 | 2/1/2023 |