DynamicWhere.ex
1.4.1
See the version list below for details.
dotnet add package DynamicWhere.ex --version 1.4.1
NuGet\Install-Package DynamicWhere.ex -Version 1.4.1
<PackageReference Include="DynamicWhere.ex" Version="1.4.1" />
paket add DynamicWhere.ex --version 1.4.1
#r "nuget: DynamicWhere.ex, 1.4.1"
// Install DynamicWhere.ex as a Cake Addin #addin nuget:?package=DynamicWhere.ex&version=1.4.1 // Install DynamicWhere.ex as a Cake Tool #tool nuget:?package=DynamicWhere.ex&version=1.4.1
DynamicWhere.ex
Description
DynamicWhere.ex is a powerful and versatile library for dynamically creating complex filter expressions in Entity Framework Core applications. This library enhances your EF Core queries by providing support for creating dynamic filters using objects, making it easier to generate complex queries for your data.
With DynamicWhere.ex, you can easily define and apply conditions, logical connectors, and intersections to filter data from your database. It offers a flexible way to construct dynamic filter expressions for various data types, including text, numbers, booleans, and date-time values, using a wide range of logical operators.
Installation
You can install the library via NuGet. Run the following command in your project's NuGet Package Manager console:
Install-Package DynamicWhere.ex
Getting Started
Getting started with the library is straightforward. Simply install it via NuGet, and you're ready to create dynamic filter expressions for your Entity Framework Core queries.
Usage
DynamicWhere.ex provides enums, classes, and extension methods to simplify the construction of dynamic filter expressions. You can define conditions, condition groups, and sets using objects, allowing you to specify complex filtering logic in a structured way.
Enums
The DynamicWhere.ex library includes the following enums to support dynamic querying capabilities:
DataType
The DataType
enum provides support for various data types when defining conditions in dynamic queries. It includes the following values:
Text
: Represents textual data.Number
: Represents numeric data.Boolean
: Represents boolean data.DateTime
: Represents date and time data.Guid
: Represents globally unique identifier (GUID) data.
You can use the DataType
enum to specify the data type for your dynamic query conditions, making it easier to work with different types of data, including GUIDs.
Operator
The Operator
enum offers a comprehensive set of logical comparison operators for constructing dynamic queries. It now includes both case-sensitive and case-insensitive versions of certain operators, allowing for greater flexibility in query construction. The operators are:
Equal
: Equality comparison.IEqual
: Case-insensitive equality comparison.NotEqual
: Inequality comparison.INotEqual
: Case-insensitive inequality comparison.GreaterThan
: Greater than comparison.GreaterThanOrEqual
: Greater than or equal to comparison.LessThan
: Less than comparison.LessThanOrEqual
: Less than or equal to comparison.Contains
: Substring containment check.IContains
: Case-insensitive substring containment check.NotContains
: Negation of substring containment check.INotContains
: Negation of case-insensitive substring containment check.StartsWith
: Prefix check.IStartsWith
: Case-insensitive prefix check.NotStartsWith
: Negation of prefix check.INotStartsWith
: Negation of case-insensitive prefix check.EndsWith
: Suffix check.IEndsWith
: Case-insensitive suffix check.NotEndsWith
: Negation of suffix check.INotEndsWith
: Negation of case-insensitive suffix check.In
: Membership check.IIn
: Case-insensitive membership check.NotIn
: Negation of membership check.INotIn
: Negation of case-insensitive membership check.Between
: Range comparison.NotBetween
: Negation of range comparison.IsNull
: Null check.IsNotNull
: Negation of null check.
These operators can be used in combination with the library's extension methods to create complex dynamic queries with both case-sensitive and case-insensitive comparisons, providing greater flexibility in query construction.
Connector
The Connector
enum provides logical connectors that allow you to combine conditions within a query. It includes the following connectors:
And
: Represents the logical "AND" connector.Or
: Represents the logical "OR" connector.
You can use these connectors to specify how conditions should be combined in your dynamic queries, enabling flexible query construction.
Intersection
The Intersection
enum is used to define how multiple sets of conditions should be combined in a query. It includes the following intersection types:
Union
: Represents the union of sets, combining conditions with "OR" logic.Intersect
: Represents the intersection of sets, combining conditions with "AND" logic.Except
: Represents the difference between sets, excluding conditions that meet specified criteria.
These intersection types are valuable when you need to apply logical operations to multiple sets of conditions in your dynamic queries.
Direction
The Direction
enum is used to specify the sorting direction in queries. It includes the following sorting directions:
Ascending
: Represents ascending sorting direction.Descending
: Represents descending sorting direction.
You can use the Direction
enum when defining sorting preferences for your queries to control whether the results should be sorted in ascending or descending order.
Classes
The DynamicWhere.ex library includes the following classes that enable you to construct dynamic queries:
Condition
The Condition
class represents an individual condition in a dynamic query. It contains the following properties:
Sort
: An integer that specifies the sort order of the condition.Field
: A string that indicates the field or property to which the condition applies.DataType
: An instance of theDataType
enum, specifying the data type of the condition.Operator
: An instance of theOperator
enum, defining the logical comparison operator for the condition.Values
: A list of strings representing the values to compare against. This list may contain one or more values, depending on the operator.
You can create instances of the Condition
class to define individual conditions within your dynamic queries.
ConditionGroup
The ConditionGroup
class represents a group of conditions that are logically combined within a dynamic query. It includes the following properties:
Sort
: An integer that determines the sort order of the condition group.Connector
: An instance of theConnector
enum, specifying how conditions within the group should be connected (using "AND" or "OR" logic).Conditions
: A list ofCondition
objects representing the conditions within the group.SubConditionGroups
: A list ofConditionGroup
objects, allowing for nested groups of conditions.
You can use the ConditionGroup
class to create complex conditions by combining multiple conditions and nesting groups as needed.
ConditionSet
The ConditionSet
class represents a set of conditions in a dynamic query. It includes the following properties:
Sort
: An integer that defines the sort order of the condition set.Intersection
: An instance of theIntersection
enum, indicating how conditions within the set should be combined (union, intersection, or exclusion).ConditionGroup
: An instance of theConditionGroup
class representing the group of conditions within the set.
You can use the ConditionSet
class to create sets of conditions and specify how those conditions should be combined within your dynamic queries.
Segment
The Segment
class serves as the top-level container for dynamic queries. It includes the following property:
ConditionSets
: A list ofConditionSet
objects representing multiple sets of conditions within a query.
You can use the Segment
class to organize and manage multiple sets of conditions in your dynamic queries.
OrderBy
The OrderBy
class is used to configure sorting in dynamic queries. It includes the following properties:
Sort
: An integer representing the sort order.Field
: A string indicating the field or property by which to sort the query results.Direction
: An instance of theDirection
enum, specifying the sorting direction, which can be either ascending or descending. The default direction is ascending.
You can use the OrderBy
class to specify how the query results should be sorted based on the chosen field and sorting direction. It plays a crucial role in customizing the order of your dynamic query results.
By utilizing the OrderBy
class in your dynamic queries, you can achieve precise control over the sorting behavior, ensuring that the results are organized according to your requirements.
PageBy
The PageBy
class is used to configure pagination settings for dynamic queries. It includes the following properties:
PageNumber
: An integer representing the desired page number.PageSize
: An integer indicating the number of items to display per page.
By utilizing the PageBy
class in your dynamic queries, you can control the pagination behavior, specifying which page of results to retrieve and how many items should be displayed on each page. This is essential for managing large sets of data and presenting it to users in a user-friendly manner.
Filter
The Filter
class serves as a configuration container for dynamic queries. It encompasses the following components:
ConditionGroup
(nullable): Represents a condition group that contains a list of conditions and a logical operator. This allows you to create complex queries with multiple conditions. If set tonull
, it will not affect the query.Orders
(nullable): A list of order-by criteria that specify how the query results should be sorted. If set tonull
, it will not affect the query's sorting.Page
(nullable): Pagination settings that determine the page number and the number of items to display per page. If set tonull
, it will not affect the query's pagination.
By utilizing the Filter
class, you can conveniently define conditions, sorting rules, and pagination settings for your dynamic queries. This flexibility allows you to create dynamic queries tailored to your specific requirements, and it accommodates scenarios where you may not need to specify certain filtering, sorting, or pagination criteria.
These classes provide a powerful foundation for constructing dynamic queries using the DynamicWhere.ex library, offering fine-grained control over your data retrieval and presentation.
Extension Methods
The DynamicWhere.ex library includes a set of extension methods that enhance the functionality of LINQ queries for dynamic querying purposes. Below are the public extension methods provided by the library:
ToListAsync<T>(this IQueryable<T> query, Segment segment)
This extension method allows you to execute an asynchronous query and return the results as a list based on the specified segment of conditions.
Usage:
// Assuming you have an IQueryable<T> query and a Segment segment defined
List<T> results = await query.ToListAsync(segment);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to execute the dynamic query on.segment
(Segment): The segment object containing sets of conditions for dynamic querying.
Return Value:
List<T>
: A list of query results that meet the conditions specified in the segment.
Where<T>(this IQueryable<T> query, ConditionGroup group)
This extension method allows you to filter an IQueryable based on a specified ConditionGroup
.
Usage:
// Assuming you have an IQueryable<T> query and a ConditionGroup conditionGroup defined
var filteredQuery = query.Where(conditionGroup);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to filter.conditionGroup
(ConditionGroup): The condition group specifying the filtering conditions.
Return Value:
IQueryable<T>
: A new queryable instance with the specified conditions applied.
Where<T>(this IQueryable<T> query, Condition condition)
This extension method allows you to filter an IQueryable based on a single Condition
.
Usage:
// Assuming you have an IQueryable<T> query and a Condition condition defined
var filteredQuery = query.Where(condition);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to filter.condition
(Condition): The single condition specifying the filtering criteria.
Return Value:
IQueryable<T>
: A new queryable instance with the specified condition applied.
These extension methods empower you to build dynamic queries by composing conditions and filter your data based on flexible criteria.
Additional Extension Methods
Page<T>(this IQueryable<T> query, PageBy page)
This extension method allows you to apply pagination to an IQueryable, specifying the page number and page size.
Usage:
// Assuming you have an IQueryable<T> query and a PageBy page defined
var pagedQuery = query.Page(page);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to apply pagination to.page
(PageBy): The page object specifying the page number and page size.
Return Value:
IQueryable<T>
: A new queryable instance with pagination applied.
Order<T>(this IQueryable<T> query, OrderBy order)
This extension method allows you to order the results of an IQueryable based on a specified OrderBy
configuration.
Usage:
// Assuming you have an IQueryable<T> query and an OrderBy order defined
var orderedQuery = query.Order(order);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to order.order
(OrderBy): The order-by configuration specifying the field and sorting direction.
Return Value:
IQueryable<T>
: A new queryable instance with the specified ordering applied.
Order<T>(this IQueryable<T> query, List<OrderBy> orders)
This extension method allows you to order the results of an IQueryable based on a list of OrderBy
configurations.
Usage:
// Assuming you have an IQueryable<T> query and a List<OrderBy> orders defined
var orderedQuery = query.Order(orders);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to order.orders
(List<OrderBy>): A list of order-by configurations specifying the fields and sorting directions.
Return Value:
IQueryable<T>
: A new queryable instance with the specified ordering applied.
Filter<T>(this IQueryable<T> query, Filter filter)
This extension method allows you to filter an IQueryable based on a Filter
configuration, including conditions, sorting, and pagination.
Usage:
// Assuming you have an IQueryable<T> query and a Filter filter defined
var filteredQuery = query.Filter(filter);
Documentation:
Parameters:
query
(IQueryable<T>): The queryable source to filter.filter
(Filter): The filter configuration specifying conditions, sorting, and pagination.
Return Value:
IQueryable<T>
: A new queryable instance with the specified filtering, ordering, and pagination applied.
These additional extension methods extend your capabilities to filter, order, and paginate data within your dynamic queries for more comprehensive data manipulation.
JSON Examples
Condition
- Condition with a single value
{
"Sort": 1,
"Field": "ProductName",
"DataType": "Text",
"Operator": "Equal",
"Values": ["apple"]
}
Condition Group
- Condition Group with 3 Conditions and 2 Subgroups
- Each Subgroup with 2 Conditions
{
"Sort": 1,
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "Price",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["10"]
},
{
"Sort": 2,
"Field": "Category",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Electronics"]
},
{
"Sort": 3,
"Field": "InStock",
"DataType": "Boolean",
"Operator": "Equal",
"Values": ["true"]
}
],
"SubConditionGroups": [
{
"Sort": 1,
"Connector": "Or",
"Conditions": [
{
"Sort": 1,
"Field": "Discount",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["20"]
},
{
"Sort": 2,
"Field": "Brand",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Sony"]
}
],
"SubConditionGroups": []
},
{
"Sort": 2,
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "ShippingDate",
"DataType": "DateTime",
"Operator": "GreaterThan",
"Values": ["2023-01-01"]
},
{
"Sort": 2,
"Field": "ShippingDate",
"DataType": "DateTime",
"Operator": "LessThanOrEqual",
"Values": ["2023-12-31"]
}
],
"SubConditionGroups": []
}
]
}
Segment
- Segment with 2 Sets
- Each Set with a Condition Group
- Each Condition Group with 3 Conditions and 2 Subgroups
- Each Subgroup with 2 Conditions
{
"ConditionSets": [
{
"Sort": 1,
"Intersection": "Union",
"ConditionGroup": {
"Sort": 1,
"Connector": "Or",
"Conditions": [
{
"Sort": 1,
"Field": "Rating",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["4.5"]
},
{
"Sort": 2,
"Field": "Reviews",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["100"]
},
{
"Sort": 3,
"Field": "Discount",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["30"]
}
],
"SubConditionGroups": [
{
"Sort": 1,
"Connector": "Or",
"Conditions": [
{
"Sort": 1,
"Field": "Brand",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Samsung"]
},
{
"Sort": 2,
"Field": "Brand",
"DataType": "Text",
"Operator": "Equal",
"Values": ["LG"]
}
],
"SubConditionGroups": []
},
{
"Sort": 2,
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "InStock",
"DataType": "Boolean",
"Operator": "Equal",
"Values": ["true"]
},
{
"Sort": 2,
"Field": "Category",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Appliances"]
}
],
"SubConditionGroups": []
}
]
}
},
{
"Sort": 2,
"Intersection": "Intersect",
"ConditionGroup": {
"Sort": 1,
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "Color",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Red"]
},
{
"Sort": 2,
"Field": "Size",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Large"]
},
{
"Sort": 3,
"Field": "Weight",
"DataType": "Number",
"Operator": "LessThanOrEqual",
"Values": ["5"]
}
],
"SubConditionGroups": [
{
"Sort": 1,
"Connector": "Or",
"Conditions": [
{
"Sort": 1,
"Field": "Price",
"DataType": "Number",
"Operator": "LessThanOrEqual",
"Values": ["50"]
},
{
"Sort": 2,
"Field": "Rating",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["4"]
}
],
"SubConditionGroups": []
},
{
"Sort": 2,
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "Category",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Clothing"]
},
{
"Sort": 2,
"Field": "Season",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Summer"]
}
],
"SubConditionGroups": []
}
]
}
}
]
}
These JSON examples demonstrate various scenarios of conditions, condition groups, and segments that can be used with the library.
PageBy
In this example, we specify that we want to retrieve the second page of data, with each page containing 10 items.
{
"PageNumber": 2,
"PageSize": 10
}
OrderBy
This JSON example represents an ordering configuration where we want to sort the data by the "ProductName" field in ascending order.
{
"Sort": 1,
"Field": "ProductName",
"Direction": "Ascending"
}
Filter
This JSON example represents a filter configuration with the following components:
ConditionGroup
: A set of conditions combined using the "And" logical operator.- Condition 1: Filter products in the "Electronics" category.
- Condition 2: Filter products with a price greater than 100.
Orders
: Specifies the ordering criteria.- Order 1: Sort products by "ProductName" in ascending order.
- Order 2: Then sort products by "Price" in descending order.
Page
: Specifies that we want the first page of results with a page size of 20 items.
{
"ConditionGroup": {
"Connector": "And",
"Conditions": [
{
"Sort": 1,
"Field": "Category",
"DataType": "Text",
"Operator": "Equal",
"Values": ["Electronics"]
},
{
"Sort": 2,
"Field": "Price",
"DataType": "Number",
"Operator": "GreaterThan",
"Values": ["100"]
}
]
},
"Orders": [
{
"Sort": 1,
"Field": "ProductName",
"Direction": "Ascending"
},
{
"Sort": 2,
"Field": "Price",
"Direction": "Descending"
}
],
"Page": {
"PageNumber": 1,
"PageSize": 20
}
}
These JSON examples demonstrate how you can configure PageBy
, OrderBy
, and Filter
settings for dynamic querying of data.
License
This library is released under a free and open-source license, allowing you to use it in your projects without restrictions.
Change Log
All notable changes to the DynamicWhere.ex library will be documented in this section.
[v1.4.1] - 2023-09-18
Enhanced Flexibility
- The
Filter
configuration in dynamic queries has been improved for greater flexibility. ConditionGroup
,Orders
, andPage
objects are now nullable within theFilter
class.- This change allows you to use any combination of
ConditionGroup
,Orders
, orPage
based on your specific query requirements. - If any of these objects are set to
null
, they will not impact the query, providing more adaptable and versatile query configurations.
[v1.4.0] - 2023-09-14
Added
- Added support for pagination, allowing users to specify page numbers and page sizes using the
PageBy
class. - Implemented the ability to define sorting criteria using the
OrderBy
class. - Introduced the
Filter
class, enabling users to configure complex dynamic queries.
[v1.3.0] - 2023-09-13
Refactored
- Refactored and improved codebase for better maintainability.
- Added comprehensive documentation, summaries, and comments to enhance code readability.
- Introduced meaningful names and structuring to make code cleaner and more understandable.
[v1.2.0] - 2023-09-12
Added
- Added support for the GUID data type, allowing filtering and comparisons using GUID values.
- Enabled case-insensitive comparisons for text data types.
- Introduced the ability to specify nested property names in conditions.
[v1.0.0] - 2023-09-11
Initial Release
- The DynamicWhere.ex library is released, providing dynamic querying capabilities for LINQ queries.
Credits
This extension is built upon the foundation of System.Linq.Dynamic.Core, and we extend our appreciation to the authors and contributors of the original library for their valuable work.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. 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. |
-
net6.0
- Microsoft.EntityFrameworkCore (>= 6.0.22)
- System.Linq.Dynamic.Core (>= 1.3.4)
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 |
---|---|---|
1.8.4 | 89 | 10/12/2024 |
1.8.3 | 91 | 8/8/2024 |
1.8.2 | 82 | 7/10/2024 |
1.8.1 | 520 | 3/29/2024 |
1.8.0 | 207 | 2/11/2024 |
1.7.2 | 118 | 2/9/2024 |
1.7.1 | 106 | 2/8/2024 |
1.7.0 | 284 | 11/5/2023 |
1.6.0 | 185 | 9/30/2023 |
1.5.3 | 174 | 9/25/2023 |
1.5.2 | 180 | 9/24/2023 |
1.5.1 | 154 | 9/23/2023 |
1.5.0 | 138 | 9/22/2023 |
1.4.3 | 146 | 9/21/2023 |
1.4.2 | 153 | 9/19/2023 |
1.4.1 | 162 | 9/18/2023 |
1.4.0 | 161 | 9/14/2023 |
1.3.0 | 147 | 9/13/2023 |
1.2.0 | 172 | 9/12/2023 |
1.0.2 | 195 | 9/11/2023 |
1.0.1 | 175 | 9/11/2023 |
1.0.0 | 179 | 9/11/2023 |