Row-level multi-tenancy in ASP.NET Core: one marker, one filter, one primer
How to make tenant isolation a property of the data layer instead of a discipline problem — with a real multi-tenant fleet-management API as the case study.
Patterns, gotchas and small wins from building the Regira packages and modules — entity pipelines, editorial front-ends and everything between.
How to make tenant isolation a property of the data layer instead of a discipline problem — with a real multi-tenant fleet-management API as the case study.
How ?brandId=1&hasIntervention=true becomes SQL: one typed object that names your filters, one small builder that translates them - the foundation of the read pipeline, with a runnable sample to curl along.
The full read surface a registration exposes, why counts live next to pages, and how POSTing an array of SearchObjects gives OR a principled home - closing out the filtering series.
One interface turns DELETE into soft delete: archived rows vanish from every query, stay reachable on purpose via ?archived=, and come back with a plain save - every step runnable against the sample API.
The rest of the read pipeline: repeatable sort enums (and the OrderOrThenBy trap), flags-enum includes that keep list payloads lean, and page-size clamps enforced once at the HTTP boundary.
How to turn ?brand=volvo&hasIntervention=true into safe, index-friendly SQL — a deep dive into typed search objects, query builders, global filters, normalized free-text search and union queries.
Cross-cutting predicates - id filters, soft delete, tenancy - registered once against an interface and provably applied everywhere, including the key-type mechanics that keep security defaults from silently dropping.