BlogDoFT.Libs.EntityFramework.CodeGenerator
10.1.0
dotnet add package BlogDoFT.Libs.EntityFramework.CodeGenerator --version 10.1.0
NuGet\Install-Package BlogDoFT.Libs.EntityFramework.CodeGenerator -Version 10.1.0
<PackageReference Include="BlogDoFT.Libs.EntityFramework.CodeGenerator" Version="10.1.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="BlogDoFT.Libs.EntityFramework.CodeGenerator" Version="10.1.0" />
<PackageReference Include="BlogDoFT.Libs.EntityFramework.CodeGenerator"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
paket add BlogDoFT.Libs.EntityFramework.CodeGenerator --version 10.1.0
#r "nuget: BlogDoFT.Libs.EntityFramework.CodeGenerator, 10.1.0"
#:package BlogDoFT.Libs.EntityFramework.CodeGenerator@10.1.0
#addin nuget:?package=BlogDoFT.Libs.EntityFramework.CodeGenerator&version=10.1.0
#tool nuget:?package=BlogDoFT.Libs.EntityFramework.CodeGenerator&version=10.1.0
BlogDoFT.Libs.EntityFramework.CodeGenerator
A Roslyn Source Generator that reads filter DTOs annotated with BlogDoFT.Libs.EntityFramework.CodeGenerator.Abstractions.GeneratePredicateAttribute<TEntity> and emits:
ToPredicate()→Expression<Func<TEntity, bool>>HasFilter()→bool
The generated predicates are provider-aware:
- On PostgreSQL (when
Npgsql.EntityFrameworkCore.PostgreSQLis referenced), string filters with%useILIKE. - On other providers, string filters with
%useEF.Functions.Like. - No reflection is used; the generator detects
NpgsqlDbFunctionsExtensions.ILikeat compile-time.
Target Framework:
netstandard2.0(Analyzer-friendly)
C# Language Version: latest
Installation
Install the NuGet package:
dotnet add package BlogDoFT.Libs.EntityFramework.CodeGenerator.Generators
The application must also reference
BlogDoFT.Libs.EntityFramework.CodeGenerator.Abstractions.
How it works
- The generator scans the compilation for classes annotated with
[GeneratePredicate<TEntity>]; - It validates the DTO is
partial; otherwise it reports PG001 (error). - It discovers filterable properties annotated with:
StringFilterAttributeNumericFilterAttributeTemporalFilterAttributeBooleanFilterAttribute
- It detects at compile-time whether
NpgsqlDbFunctionsExtensions.ILike(DbFunctions, string, string)is available:- If present → emits code that builds expression calls to ILIKE
- If absent → emits code that falls back to LIKE
- It generates partial members
HasFilter()andToPredicate()into the same DTO namespace and type.
Example end-to-end
Entity
namespace Domain;
public class UserRecord
{
public Guid Id { get; set; }
public string Name { get; set; } = "";
public string Email { get; set; } = "";
public int Age { get; set; }
public DateTime CreatedAt { get; set; }
public bool Active { get; set; }
}
Filter DTO
using BlogDoFT.Libs.EntityFramework.CodeGenerator.Abstractions;
[GeneratePredicate<Domain.UserRecord>]
public partial class UserFilterDto
{
[StringFilter(TargetProperty = nameof(Domain.UserRecord.Name), Order = 1)]
public string? Name { get; init; }
[StringFilter(TargetProperty = nameof(Domain.UserRecord.Email), Order = 2)]
public string? Email { get; init; }
[NumericFilter(TargetProperty = nameof(Domain.UserRecord.Age), Operator = ComparisonOperator.GreaterThanOrEqual)]
public int? MinimumAge { get; init; }
[TemporalFilter(TargetProperty = nameof(Domain.UserRecord.CreatedAt), Operator = ComparisonOperator.LessThanOrEqual)]
public DateTime? CreatedUntil { get; init; }
[BooleanFilter(TargetProperty = nameof(Domain.UserRecord.Active))]
public bool? Active { get; init; }
}
Query with EF Core
var filter = new UserFilterDto
{
Name = "%ann%",
MinimumAge = 18,
Active = true
};
var predicate = filter.ToPredicate();
var users = await db.Set<UserRecord>()
.Where(predicate)
.ToListAsync();
String pattern rules
- If the value does not contain
%, the generator emits equality (field == value). - If the value contains
%, the generator emits a database pattern using:ILIKE(PostgreSQL with Npgsql)LIKE(fallback on other providers) This way you keep multi-database compatibility while getting case-insensitive matching on PostgreSQL.
If you want to support
*as a wildcard in input, normalize it to%in your DTO before callingToPredicate().
Requirements
- BlogDoFT.Libs.EntityFramework.CodeGenerator.Abstractions must be referenced by the app
- C# 11+ (generic attributes) in the app project
- EF Core 6/7/8+
Troubleshooting
The generated methods are missing
- Ensure the DTO is marked as
partial; - Ensure the app references BlogDoFT.Libs.EntityFramework.CodeGenerator.Abstractions and the generator as Analyzer.
- Clean and rebuild the solution.
I want to see SQL logs
Install and configure console logging:
<PackageReference Include="Microsoft.Extensions.Logging.Console" />
services.AddLogging(b =>
{
b.ClearProviders();
b.AddSimpleConsole();
b.AddFilter("Microsoft.EntityFrameworkCore.Database.Command", LogLevel.Information);
});
Add in your DbContext Options:
options
.UseLoggerFactory(loggerFactory)
.EnableSensitiveDataLogging()
.EnableDetailedErrors();
Versioning
Starting with v10.0.0, this library's version numbering follows the major version of the .NET runtime it targets. For example, this version is compatible with .NET 10, so the major version is 10 — this explains the jump from the previous 1.x version series.
| 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. 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. |
| .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
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 |
|---|---|---|
| 10.1.0 | 42 | 9/14/2026 |
| 10.0.1 | 45 | 9/14/2026 |
| 10.0.0 | 45 | 9/13/2026 |
| 1.14.0 | 53 | 9/13/2026 |
| 1.13.0 | 45 | 9/13/2026 |
| 1.12.0 | 100 | 8/27/2026 |
| 1.11.0 | 96 | 8/27/2026 |
| 1.10.0 | 359 | 11/16/2025 |
| 1.9.0 | 240 | 11/5/2025 |
| 1.8.0 | 236 | 11/3/2025 |
| 1.7.0 | 240 | 11/3/2025 |
| 1.6.3 | 230 | 10/21/2025 |
| 1.6.2 | 223 | 10/21/2025 |
| 1.6.1 | 231 | 10/21/2025 |
| 1.6.0 | 230 | 10/21/2025 |