Entity Framework Core

Entity Framework Core (EF Core) powers FlexBase’s relational story, but it is not wired as a “DataStore Provider” the way document DB, file store, etc. are.

In generated apps, relational infrastructure is organized under:

  • Infrastructure/Db/* (EF DbContext base + provider-specific repositories/bridges + connection providers)

  • EndPoints/DbMigrations/* (provider-specific migrations runners)

Why it matters

  • Change Tracking keeps entity graphs in sync during persistence.

  • LINQ/Projection simplifies reporting and pagination from handlers.

  • Navigation properties let you compose rich joins when handlers need related data.

  • Resilience features from EF Core keep transient failures transparent to your handlers.

Flex note: for async IQueryable<T> execution, prefer Sumeru.Flex.FlexQueryableAsyncExtensions (e.g., ToListAsyncFlex, FirstOrDefaultAsyncFlex) over EF Core’s native async query helpers.

Infrastructure Arrangement

Rather than inventing domain repositories, generated code leans on DomainHandler/.../Queries and DomainHandler/.../Handlers folders (for example List{Entities}, Create{Entity}Handler, etc.). Each query/handler receives relational services through DI (for example IRepoFactory, IPostBus, logging), executes LINQ queries or persists changes, and then publishes events.

Typical layout:

  • EF base context: Infrastructure/Db/{YourApplication}.BaseEF/ApplicationEFDbContext.cs

  • Provider-specific repos/bridges: Infrastructure/Db/{YourApplication}.BaseEF.SqlServer/*, ...PostgreSql/*, ...MySql/*

  • Connection providers (appsettings-driven): Infrastructure/Db/{YourApplication}.BaseEF/ConnectionProviders/*

  • Migrations runners: EndPoints/DbMigrations/{YourApplication}.Migrations.{Provider}/*

Handler Example (Insert/Update)

Handlers typically:

  1. Hydrate the request context (cmd.Dto.GetAppContext())

  2. Initialize relational context with the DTO parameters

  3. Create/update the domain model

  4. Persist changes

  5. Optionally raise follow-up events through the generated Fire(...) pipeline

Both handlers keep the intent logic in the command class while reusing the generated infrastructure for EF Core context resolution and event publishing.

Sample Usage

Simple list example (lookup)

Use a simple enumerable query for “lookup” lists (the pattern matches typical Get{Entity}ForLookup queries).

Get-by-id example

Use a single-result query for Get{Entity}ById patterns.

Handlers follow this approach—initialize relational context, project entities, and return DTOs—so you can rely on the same pattern across modules.

Configuration Keys

  1. FlexBase:AppDbConnection – Primary relational connection string.

If you need separate read/write connections or tenant/master connections, follow the provider-specific connection providers under Infrastructure/Db/*/ConnectionProviders.

Best Practices

  1. Stick to the handlers/queries in DomainHandler/... so the generator can update wiring and keep telemetry consistent.

  2. Emit events via PostBus inside handlers like CreateApplicationHandler/SubmitReferralHandler to keep integration points decoupled.

  3. Use DTO projections (see ListApplications) to keep EF Core in read-only mode when possible.

Testing & Tooling

  • Unit tests typically execute the generated queries/handlers directly and provide any relational dependencies through DI.

Provider-Specific SQL (ProviderSqlMap)

When you need raw SQL that differs per provider (SQL Server vs PostgreSQL vs MySQL), use ProviderSqlMap so a repository can pick the correct SQL based on the configured EF provider.

Soft Delete Filter

If your entities derive from TFlex, you can enable a global query filter that hides rows where IsDeleted is true.

Enable either:

  • Per context: context.UseSoftDeleteFilters()

  • Via DI: FlexSoftDeleteOptions (e.g., Enabled = true)

To include deleted rows for a scope:

Audit Trail

To capture audit trail rows for Added/Modified/Deleted entities, enable audit trail behavior on the EF context / interceptor as documented.

Typical options:

  • Enable on your FlexEFDbContext implementation (often a one-liner such as EnableAuditTrail()).

  • Or register an interceptor and options in DI and attach it via AddDbContext.

Querying audit trails is then just a normal EF query:

Last updated