Storing and Querying a Hierarchy of Types with Marten
Jeremy D. Miller shows how Marten stores a class hierarchy in one PostgreSQL table and queries it with LINQ, without the table-per-type or table-per-concrete-type decisions EF Core requires. He also covers subtype-specific partial indexes and duplicated fields. For teams weighing document storage against EF Core inheritance mapping, it is a useful comparison.
Key points
- Register subtypes with AddSubClassHierarchy() or an explicit list; the explicit list is safer for large assemblies.
- The whole hierarchy lives in one table, with an mt_doc_type discriminator column and an automatic btree index on it.
- Base type queries return concrete subtypes, and LoadAsync<CryptoPayment>(id) returns null for another subtype's document.
- Discriminator values come from class names, so pin renamed subtypes with MappedType to avoid orphaned rows.
- Duplicate<TSub>() creates a real column for a subtype field, and a Predicate on an index makes a partial index for one subtype.
- Subtype-only properties need no migration, because new properties simply appear in the stored JSON.
Jeremy D. Miller explains how Marten stores and queries class hierarchies. EF Core asks you to pick a table-mapping strategy up front, and each choice changes the schema and generated SQL. Marten avoids that decision because documents live as JSONB in PostgreSQL, so the hierarchy fits into a single table.
The base type and its subclasses share one table with a discriminator column that Marten derives from the type name, so each row stores only its own JSON. Querying the base type returns concrete subtypes, while subtype queries add the discriminator filter automatically. Partial indexes can target a single subtype, and Duplicate<TSub>() promotes a subtype property into a real column. Shared-table costs such as autovacuum and bloat still apply.
Real-world use
- A payments service where card, bank transfer and crypto payments share one API and one PostgreSQL table.
- A reporting screen that filters all payments by amount and date, then narrows to one subtype with a partial index.
- A team using Marten projections that wants inheritance-style document models without EF Core mapping decisions.
Why it matters
Because Marten needs no TPH, TPT or TPC decision, schema upkeep and subtype query tuning take far less effort. Still, one hot table shares autovacuum and bloat costs across all subtypes, so weigh write rates before adopting it.
Related stories
- Sending leads to Odoo without losing one: a transactional outbox in ASP.NET CoreDEV Community: #aspnetcore2 d ago
- Idempotent NebulaGraph bulk ingestion from .NET using deterministic VIDsDEV Community: #csharp3 d ago
- TableSchema and database structure upgrades: compare, plan, executeDEV Community: #dotnet3 d ago