BlogDoFT.Libs.EntityFramework.CodeGenerator
1.7.0
See the version list below for details.
dotnet add package BlogDoFT.Libs.EntityFramework.CodeGenerator --version 1.7.0
NuGet\Install-Package BlogDoFT.Libs.EntityFramework.CodeGenerator -Version 1.7.0
<PackageReference Include="BlogDoFT.Libs.EntityFramework.CodeGenerator" Version="1.7.0"> <PrivateAssets>all</PrivateAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> </PackageReference>
<PackageVersion Include="BlogDoFT.Libs.EntityFramework.CodeGenerator" Version="1.7.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 1.7.0
#r "nuget: BlogDoFT.Libs.EntityFramework.CodeGenerator, 1.7.0"
#:package BlogDoFT.Libs.EntityFramework.CodeGenerator@1.7.0
#addin nuget:?package=BlogDoFT.Libs.EntityFramework.CodeGenerator&version=1.7.0
#tool nuget:?package=BlogDoFT.Libs.EntityFramework.CodeGenerator&version=1.7.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();
| 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.