MasterNeverDown.DataFilter
1.0.3
dotnet add package MasterNeverDown.DataFilter --version 1.0.3
NuGet\Install-Package MasterNeverDown.DataFilter -Version 1.0.3
<PackageReference Include="MasterNeverDown.DataFilter" Version="1.0.3" />
<PackageVersion Include="MasterNeverDown.DataFilter" Version="1.0.3" />
<PackageReference Include="MasterNeverDown.DataFilter" />
paket add MasterNeverDown.DataFilter --version 1.0.3
#r "nuget: MasterNeverDown.DataFilter, 1.0.3"
#:package MasterNeverDown.DataFilter@1.0.3
#addin nuget:?package=MasterNeverDown.DataFilter&version=1.0.3
#tool nuget:?package=MasterNeverDown.DataFilter&version=1.0.3
MasterNeverDown.DataFilter - Expression Tree Filter Extension
A high-performance, type-safe generic filter library for C# that uses Expression Trees to dynamically build LINQ query conditions. Designed for IQueryable<T> (e.g., EF Core) to enable database-level filtering (instead of in-memory filtering), significantly improving performance for large datasets.
📦 Installation
.NET CLI
dotnet add package MasterNeverDown.DataFilter
NuGet Package Manager
Install-Package MasterNeverDown.DataFilter
PackageReference
<PackageReference Include="MasterNeverDown.DataFilter" Version="1.0.0" />
🚀 Quick Start
Step 1: Define Your Entity
public class User
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public int Age { get; set; }
public DateTime CreateTime { get; set; }
public string? Email { get; set; }
// Nested property example
public UserProfile Profile { get; set; } = new UserProfile();
}
public class UserProfile
{
public string Address { get; set; } = string.Empty;
public int PhoneNumber { get; set; }
}
Step 2: Build Filter Conditions
using GenericFilter.Models;
using GenericFilter.Enums;
using GenericFilter.Extensions;
// Create filter request
var filterRequest = new FilterRequest
{
UseAndLogic = true, // Use AND to combine conditions (default: true)
Conditions = new List<FilterCondition>
{
// Age >= 25
new FilterCondition
{
FieldName = "Age",
Operator = FilterOperator.GreaterThanOrEqual,
Value = 25
},
// Name contains "Zhang" (case-insensitive in EF Core)
new FilterCondition
{
FieldName = "Name",
Operator = FilterOperator.Contains,
Value = "Zhang"
},
// Nested property: Profile.Address contains "Beijing"
new FilterCondition
{
FieldName = "Profile.Address",
Operator = FilterOperator.Contains,
Value = "Beijing"
},
// Email is not null
new FilterCondition
{
FieldName = "Email",
Operator = FilterOperator.IsNotNull,
Value = null
}
}
};
Step 3: Apply Filter to Query
// For in-memory collections (IEnumerable)
var users = new List<User> { /* Your data */ }.AsQueryable();
var filteredUsers = users.ApplyExpressionFilter(filterRequest).ToList();
// For EF Core (database-level filtering)
// var filteredDbUsers = _dbContext.Users.ApplyExpressionFilter(filterRequest).ToListAsync();
✨ Core Features
Supported Filter Operators
| Operator | Description | Example |
|---|---|---|
Equals |
Exact match | FieldName = "Id", Value = 1 |
NotEquals |
Not match | FieldName = "Name", Value = "Li" |
GreaterThan |
Value > filter value | FieldName = "Age", Value = 20 |
GreaterThanOrEqual |
Value >= filter value | FieldName = "Age", Value = 25 |
LessThan |
Value < filter value | FieldName = "CreateTime", Value = DateTime.Now |
LessThanOrEqual |
Value ⇐ filter value | FieldName = "CreateTime", Value = DateTime.Now |
Contains |
String contains (EF Core translates to LIKE) | FieldName = "Name", Value = "Zhang" |
NotContains |
String does not contain | FieldName = "Name", Value = "Wang" |
StartsWith |
String starts with | FieldName = "Email", Value = "zhang@" |
EndsWith |
String ends with | FieldName = "Email", Value = "@example.com" |
IsNull |
Property is null | FieldName = "Email", Value = null |
IsNotNull |
Property is not null | FieldName = "Email", Value = null |
Key Advantages
- High Performance: Translates to SQL (for EF Core) and filters at the database level (no in-memory overhead)
- Type Safety: Compile-time checking for property names and value types
- Nested Properties: Support for nested properties (e.g.,
Profile.Address,Order.Product.Name) - Flexible Logic: Combine conditions with AND/OR logic
- Automatic Type Conversion: Converts filter values to match property types (e.g., string "25" → int 25)
- EF Core Compatibility: Fully compatible with EF Core 6+/7+/8+ (translates to efficient SQL)
📚 API Reference
Extension Method: ApplyExpressionFilter<T>
| Parameter | Type | Description |
|---|---|---|
source |
IQueryable<T> |
The original query to filter |
filterRequest |
FilterRequest |
The filter conditions and logic |
| Return | IQueryable<T> |
Filtered query (can be further chained with other LINQ methods) |
Model: FilterRequest
| Property | Type | Description | Default |
|---|---|---|---|
Conditions |
List<FilterCondition> |
List of filter conditions | Empty list |
UseAndLogic |
bool |
If true, combine conditions with AND; if false, use OR |
true |
Model: FilterCondition
| Property | Type | Description |
|---|---|---|
FieldName |
string |
Name of the property to filter (supports nested properties like "Profile.Address") |
Operator |
FilterOperator |
The filter operator (e.g., Contains, GreaterThan) |
Value |
object? |
The value to filter against (null for IsNull/IsNotNull) |
💡 Advanced Examples
Example 1: OR Logic Combination
var filterRequest = new FilterRequest
{
UseAndLogic = false, // Use OR instead of AND
Conditions = new List<FilterCondition>
{
new FilterCondition { FieldName = "Age", Operator = "GreaterThanOrEqual", Value = 30 },
new FilterCondition { FieldName = "Name", Operator = "Contains", Value = "Admin" }
}
};
// Result: Users where Age >=30 OR Name contains "Admin"
var filteredUsers = _dbContext.Users.ApplyExpressionFilter(filterRequest).ToListAsync();
Example 2: EF Core with Pagination/Sorting
// Combine filter with pagination and sorting
var pageNumber = 1;
var pageSize = 10;
var query = _dbContext.Users
.ApplyExpressionFilter(filterRequest)
.OrderBy(u => u.CreateTime)
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize);
var result = await query.ToListAsync();
var totalCount = await _dbContext.Users.ApplyExpressionFilter(filterRequest).CountAsync();
Example 3: Filter DateTime Properties
var filterRequest = new FilterRequest
{
Conditions = new List<FilterCondition>
{
new FilterCondition
{
FieldName = "CreateTime",
Operator = "GreaterThanOrEqual",
Value = new DateTime(2024, 1, 1)
}
}
};
// EF Core translates to: WHERE CreateTime >= '2024-01-01 00:00:00'
var filteredUsers = await _dbContext.Users.ApplyExpressionFilter(filterRequest).ToListAsync();
⚠️ Important Notes
Property Name Case Sensitivity:
- Property names must match the entity's property names (case-sensitive in C#). For example:
FieldName = "Name"(not "name" or "NAME") for a propertypublic string Name { get; set; }.
- Property names must match the entity's property names (case-sensitive in C#). For example:
EF Core Translation Limits:
- Some string operations (e.g.,
Contains) are case-insensitive in SQL Server (depends on collation), but case-sensitive in in-memory collections. - Complex nested properties (e.g.,
User.Orders[0].Product.Name) are not supported (only dot-separated nested properties likeUser.Profile.Address).
- Some string operations (e.g.,
Type Conversion:
- The library will attempt to convert the
Valueto the property's type (e.g., string "25" → int 25). If conversion fails, the condition is ignored (no exception thrown).
- The library will attempt to convert the
Null Handling:
- For
IsNull/IsNotNull, setValue = null(the value is ignored for these operators). - For nullable value types (e.g.,
int?,DateTime?),IsNull/IsNotNullworks as expected.
- For
🛠️ Troubleshooting
Common Issues
| Issue | Solution |
|---|---|
| "Property not found" error | Check that FieldName exactly matches the entity's property name (case-sensitive) and nested properties are correctly formatted (e.g., "Profile.Address" instead of "Profile_Address"). |
| Filter not working with EF Core | Ensure the operator is supported by EF Core (e.g., Contains is supported for strings, but not for numbers). Check the generated SQL with _dbContext.Users.ToQueryString() to debug. |
| Type conversion errors | Explicitly set the correct type for Value (e.g., Value = 25 instead of Value = "25" for an int property). |
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🤝 Contributing
Contributions are welcome! Please feel free to submit a Pull Request or open an Issue if you find a bug or have a feature request.
Contribution Guidelines
- Fork the repository
- Create a feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
📞 Support
If you have any questions or need help, please open an issue on the GitHub repository or contact the maintainers at [your-email@example.com].
wechat: 东百牧码人
Changelog
- v1.0.0: Initial release with core expression tree filtering functionality.
- Support for all standard filter operators and nested properties.
- Full compatibility with EF Core 6+/7+/8+ and .NET 6+/7+/8+.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. 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. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.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 |
|---|---|---|
| 1.0.3 | 73 | 1/19/2026 |