Pragmatic.Persistence.EFCore
EF Core runtime implementation for the Pragmatic persistence stack.
Overview
Section titled “Overview”Pragmatic.Persistence.EFCore bridges the gap between Pragmatic entity declarations and a working EF Core data layer. Where Pragmatic.Persistence provides the attributes and interfaces, this package provides the runtime: generated DbContexts, repository implementations, interceptors, the filter pipeline, and bulk operations.
You declare a database, the host says which module lives on it, and you get a fully configured data layer:
// In the host: declare the database…[PragmaticDatabase(Provider = DatabaseProvider.PostgreSql, ConfigKey = "ConnectionStrings:Sales")]public sealed class SalesDatabase : PragmaticDatabase;
// …and say which module lives on it. That pairing IS the topology.[Include<SalesModule, SalesDatabase>]public sealed class AppHostModule;You never write a DbContext: the generator emits one per boundary from that pairing, and the
generated host registers each of them for you.
The source generator reads each boundary’s entities and produces OnModelCreating with all
IEntityTypeConfiguration<T> calls, DbSet properties, interceptor registration, and an
Add{Boundary}DbContext() extension method for DI.
Inside a Pragmatic host that is all of it — the generated host registers the DbContexts, the
repositories and the query filters before your IStartupStep runs. Wiring it by hand, outside a host,
the three calls are:
builder.Services.AddSalesDbContext(options => options.UseNpgsql(builder.Configuration.GetConnectionString("Sales")));builder.Services.AddPragmaticPersistenceRepositories<SalesDbContext>();builder.Services.AddMyAppQueryFilters();This package is designed to work alongside Pragmatic.Persistence and the Pragmatic.SourceGenerator analyzer. All three are required for the full generated output.
Installation
Section titled “Installation”dotnet add package Pragmatic.Persistencedotnet add package Pragmatic.Persistence.EFCoreAdd the analyzer as a project reference:
<ProjectReference Include="..\Pragmatic.SourceGenerator\src\Pragmatic.SourceGenerator\Pragmatic.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />Feature Catalog
Section titled “Feature Catalog”Each feature below addresses a specific problem in EF Core data-access code. The links lead to detailed guides with examples, generated output, and design rationale.
| Problem | Solution | Guide |
|---|---|---|
Every entity needs manual IEntityTypeConfiguration<T> | Generated config from [Entity], [Relation.*], [SoftDelete], [ConcurrencyAware] | Entity Configuration |
DbContext setup is boilerplate (DbSet, OnModelCreating, DI) | [PragmaticDatabase] + [Include<TModule, TDatabase>] → complete DbContext generation | DbContext Generation |
| Repository CRUD is the same shape for every entity | Generated repos with CRUD, specs, logic-key helpers, include overloads, bulk methods | Repository Implementation |
| Timestamps, tenant and ownership fields are easy to forget | AuditingInterceptor, TenantInterceptor, OwnershipInterceptor, SoftDeleteInterceptor run on SaveChanges | Interceptors & Runtime |
Include() bypasses soft-delete and tenant filters | PragmaticQueryFilterVisitor injects .Where() into navigation expressions | Filter Pipeline |
| Inserting thousands of records one by one is slow | Generated BulkInsertAsync, BulkUpsertAsync with provider-specific SQL | Bulk Operations |
Adding [SoftDelete] to existing entities needs safe migration | Documented rollout patterns with data backfill and rollback plans | Migration Patterns |
| Integration tests need a real database with filter setup | Test harness with Testcontainers, fake ICurrentUser, filter toggle | Testing |
Documentation
Section titled “Documentation”| Guide | What You’ll Learn |
|---|---|
| DbContext Generation | [PragmaticDatabase], [Include<,>], DI registration, multi-provider support |
| Repository Implementation | Generated repository shape, keyed DI, soft-delete Remove(), IUnitOfWork |
| Entity Configuration | Property mapping, indexes, relationships, inheritance, two-level query filters |
| Interceptors & Runtime | where the ID comes from, auditing, tenant, soft-delete and ownership interceptors, value converters |
| Bulk Operations | Bulk insert/update/delete/upsert, provider SQL, concurrency options |
| Filter Pipeline | FilterMapComposer, expression visitor, EfCoreQueryExecutor integration |
| Testing | Testcontainers PostgreSQL, fixture setup, fake current user, filter toggles |
| Migration Patterns | Safe rollout for [SoftDelete], [Auditable], and schema-changing attributes |
For entity-level concepts (attributes, relationships, queries, mutations), see the Pragmatic.Persistence documentation.
Requirements
Section titled “Requirements”- .NET 10.0+
- Microsoft.EntityFrameworkCore 10.0+
License
Section titled “License”Part of the Pragmatic.Design ecosystem.