AwadyLab.EFCatalyst.PostgreSql
1.0.0
See the version list below for details.
dotnet add package AwadyLab.EFCatalyst.PostgreSql --version 1.0.0
NuGet\Install-Package AwadyLab.EFCatalyst.PostgreSql -Version 1.0.0
<PackageReference Include="AwadyLab.EFCatalyst.PostgreSql" Version="1.0.0" />
<PackageVersion Include="AwadyLab.EFCatalyst.PostgreSql" Version="1.0.0" />
<PackageReference Include="AwadyLab.EFCatalyst.PostgreSql" />
paket add AwadyLab.EFCatalyst.PostgreSql --version 1.0.0
#r "nuget: AwadyLab.EFCatalyst.PostgreSql, 1.0.0"
#:package AwadyLab.EFCatalyst.PostgreSql@1.0.0
#addin nuget:?package=AwadyLab.EFCatalyst.PostgreSql&version=1.0.0
#tool nuget:?package=AwadyLab.EFCatalyst.PostgreSql&version=1.0.0
AwadyLab.EFCatalyst
An Entity Framework Core 10 toolkit for the things most line-of-business data layers rebuild by hand: auditable, soft-deletable and multi-tenant entities, named global query filters, LINQ helpers for filtering, sorting and paging, a SaveChanges pipeline (audit, tenant guard, soft delete, concurrency, validation, integrity hashing, domain events), column encryption, change-tracking audit logs and migration helpers for views, triggers, upserts and filtered indexes.
| Package | Purpose |
|---|---|
AwadyLab.EFCatalyst.Abstraction |
Contracts and entity bases (entity interfaces and base classes, domain events, global filters, seeders, service abstractions) for domain projects. |
AwadyLab.EFCatalyst |
Every provider-neutral feature (references the abstractions). |
AwadyLab.EFCatalyst.SqlServer |
Native rowversion, deadlock detection, T-SQL for the migration helpers. |
AwadyLab.EFCatalyst.PostgreSql |
Deadlock detection, PostgreSQL SQL for the migration helpers. |
AwadyLab.EFCatalyst.Sqlite |
Sortable DateTimeOffset storage, busy/locked detection, SQLite SQL for the migration helpers. |
Targets .NET 10 and EF Core 10. All packages ship in lockstep.
Quick start
// Entities
public sealed class Order : FullAuditedAggregateRoot<int>, ITenantEntity<int>
{
public decimal Total { get; private set; }
public int TenantId { get; private set; }
public void Place() => AddDomainEvent(new OrderPlaced(Id));
}
// Context
public sealed class ShopContext(DbContextOptions<ShopContext> options) : DbContext(options)
{
public DbSet<Order> Orders => Set<Order>();
protected override void ConfigureConventions(ModelConfigurationBuilder b) =>
b.ConfigureDecimalPrecision(18, 2).ConfigureDateTimeUtc();
protected override void OnModelCreating(ModelBuilder modelBuilder) =>
modelBuilder.AddDefaultQueryFilters(this); // soft delete + tenant, as named filters
}
// Registration
services.AddEFCatalyst(o => o.Features.Validation = true);
services.AddScoped<ICurrentUserAccessor, HttpUserAccessor>(); // audit user
services.AddScoped<ICurrentTenantAccessor<int>, HttpTenantAccessor>(); // current tenant, read per query
services.AddScoped<IDomainEventDispatcher, MediatorDispatcher>(); // optional
services.AddDbContext<ShopContext>((sp, o) => o
.UseSqlServer(connectionString)
.UseEFCatalystSqlServer()
.UseEFCatalystInterceptors(sp));
Removing an Order now sets IsDeleted, DeletedAtUtc and DeletedBy; creating and updating stamp the audit
columns; new rows get the context's tenant and writes to another tenant's rows are rejected; the placed event is
dispatched after the save succeeds.
Features at a glance
- Domain —
IEntity<TKey>,ISoftDelete,IDeletionAudited,ICreationAudited,IModificationAudited,IAuditEntity,IFullAudited,ITenantEntity<T>,IRowVersion,IActiveState,IHashableEntity, and the basesEntity,AuditedEntity,SoftDeleteEntity,DeletionAuditedEntity,FullAuditedEntity,TenantEntity,AggregateRoot,FullAuditedAggregateRoot. See docs/domain.md. - Queries —
WhereIf,WhereIfNotNull,WhereIfNotNullOrWhiteSpace,WhereIfNotEmpty,WhereExists/WhereNotExists, chunkedWhereIn/WhereNotIn,OrderByIf/ThenByIf,OrderByProperty,ApplySorting,PageBy,ToPagedListAsync, keysetSlice/ToCursorPageAsync,IncludeIf,AsNoTrackingIf,IgnoreQueryFiltersIf,IncludeSoftDeleted,OnlySoftDeleted,IncludeInactive,IgnoreTenantFilter,ExecuteSoftDeleteAsync,ExecuteRestoreAsync, recursiveGetDescendantsAsync/GetAncestorsAsync. See docs/querying.md. - Interceptors — save pipeline, slow-query logging, query tagging, deadlock retry. See docs/interceptors.md.
- Model building —
IGlobalFilter<T>+AddGlobalQueryFilterInterfacesInAssembly, configuration bases, UTCDateTime, decimal precision. See docs/model-building.md. - Column security —
StoreEncrypted(AES-256-GCM),StoreMasked,StorePermutated, configured with the fluent API only. See docs/security.md. - Shadow properties and change tracking — typed shadow accessors,
WhereShadowEquals,GetChangedProperties,HasPropertyChanged,GetOriginalValue,ToAuditEntryList. See docs/change-tracking.md. - Schema and migrations —
GetTableName/GetColumnName/GetPrimaryKeys/GetMappedProperties,EnsureDatabaseDeletedAndRecreatedAsync,HasPendingMigrationsAsync,IMigrationSeeder, and migration helpers (InsertDataIfMissing,UpsertData,DeleteDataIfExists, views, functions, filtered/soft-delete indexes, soft-delete and timestamp triggers). See docs/migrations.md and docs/providers.md.
Design notes
- Performance — per-entity-type metadata is computed once per model (runtime annotations); the save pipeline
detects changes once and walks the change set once; expression trees and reflection are cached; crypto and
naming code works on pooled or stack buffers.
AwadyLab.EFCatalyst.Benchmarkscompares the pipeline with plain EF. - Security — values in migration helpers are provider-typed literals and identifiers are always quoted; dynamic sorting only binds public properties; cursors can be HMAC-signed; sensitive columns are redacted from audit entries and never appear in exception messages; query tags are sanitised. See docs/security.md.
- Public API — every public symbol is tracked in
PublicAPI.*.txt; everything else is internal.
Building
./build.ps1 # build, unit tests, 95% line / 90% branch coverage gate
./build.ps1 -Pack # also pack and verify the five packages
dotnet test AwadyLab.EFCatalyst.Tests.Integration # SQL Server + PostgreSQL containers (Docker)
dotnet run --project SampleApp # guided tour on SQLite, every scenario
dotnet run --project SampleApp -- tenancy security # selected scenarios
Sample app
SampleApp is organised like an application (Domain/, Data/ with configurations, filters and seeders,
Infrastructure/ with the composition root in SampleHost) and runs one scenario per feature area, each on a
freshly seeded database: model, tenancy, auditing, soft-delete, security, integrity, concurrency,
validation, events, change-tracking, querying, hierarchy, seeding, migrations, diagnostics.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- AwadyLab.EFCatalyst (>= 1.0.0)
- Npgsql.EntityFrameworkCore.PostgreSQL (>= 10.0.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.