v6.1.0
v6.1.0 — the modeling matrix, complete — and the documentation site
The store-neutral modeling vocabulary now lands on every store that has the concept, as that
store's native mechanism — and the project has a full documentation site:
https://equantic.github.io/core-data/
The annotation × provider matrix is closed
| Annotation | Relational (PG/MySQL/MariaDB/SQL Server) | Cosmos DB | Cassandra | MongoDB |
|---|---|---|---|---|
[Entity] / [EntityKey] / [StoredAs] / [Unmapped] |
✅ | ✅ new | ✅ new | ✅ new |
[PartitionKey] |
— | ✅ hierarchical multi-hash (≤ 3 levels), new | ✅ | — |
[ClusteringKey] |
✅ ordered index new | ✅ composite index new | ✅ native | ✅ compound index new |
[ConcurrencyToken] |
✅ | ✅ ETag | ✅ LWT, new | ✅ conditional replace, new |
[SearchIndex] |
✅ GIN trigram (PG), new | — | ✅ SASI | — |
[TimeToLive] |
— | ✅ | ✅ default_time_to_live, new |
✅ TTL index, new |
[Facet] new |
✅ varchar(n) / numeric(p,s) |
— | — | — |
Highlights
Cosmos DB: one serializer contract, end to end
CosmosEntitySerializer (System.Text.Json) applies [StoredAs]/[Unmapped] through the
serialization contract and extends the SDK's CosmosLinqSerializer, so LINQ member translation
asks the same contract: filters, sorts and projections on a renamed member hit the stored element —
a rename can never desynchronize documents from queries. Queries on [Unmapped] members refuse
loudly instead of matching nothing. Type-level Converts<TMember, TStored> keeps filter constants
converting identically to documents. Hierarchical partition keys (up to three levels) create
multi-hash containers, point writes build the multi-value key transparently, and partition
inference declines rather than guessing.
MongoDB: the fluent model it was missing
MongoModelBuilder — Collection / Key / Field / Ignore / per-member Converts /
ConcurrencyToken / ClusteringKey / TimeToLive — over the driver's class maps, so the LINQ
provider renders filters against renames and converted values. Plus MongoModel.Explain() reading
the actual driver state.
Optimistic concurrency: one exception, four native mechanisms
[ConcurrencyToken] now means the same thing everywhere — a stale write must fail, never
silently win — as a versioned WHERE (relational), an _etag If-Match (Cosmos), a
lightweight transaction (Cassandra: INSERT … IF NOT EXISTS / UPDATE … IF version = old,
refusing the LOGGED BATCH instead of degrading), and a version-filtered conditional replace
(MongoDB). All four throw ConcurrencyConflictException on the lost race.
Native TTL and search
[TimeToLive] lands as Cassandra's default_time_to_live and MongoDB's per-document TTL index
(from the lifecycle CreatedAt, or an explicit member via fluent — the semantic difference is
documented, not hidden). [SearchIndex] on PostgreSQL materializes a GIN trigram index
(pg_trgm) in EnsureCollection() — substring LIKE stops scanning; dialects without an
equivalent ignore the declaration (same semantics, unindexed plan) and Explain() says which.
Relational: composite keys, facets, ordered reads
Key(x => new { x.OrderId, x.LineNo }) — composite PRIMARY KEY DDL, point lookups by tuple
(GetAsync((orderId, lineNo))), updates/deletes addressing all key columns; keyset paging and
reference includes refuse composite targets with guidance. [Facet] sizes the DDL
(varchar(n)/nvarchar(n), numeric(p,s)). [ClusteringKey] materializes a direction-aware
multi-column index.
Explain() everywhere
All four models now report every mapping decision — names, stored types, keys, tokens, TTLs,
indexes, lifecycle — the way Explain() reports a query. Pin the lines you rely on in a test.
Documentation site
https://equantic.github.io/core-data/ — getting started per provider, the concepts and the
pushdown gates explained didactically, the full modeling matrix, per-store deep dives with the
why of every rejection, cookbook (multi-tenancy, value objects, auditing, a coming-from-EF
translation table), architecture/SPI guides, and the complete API reference generated from the
source docs. Every API shape shown was verified against the source.
Verification
All integration suites green against real stores: PostgreSQL 51, Cosmos DB 41 (vNext emulator,
hierarchical keys proven end to end), MongoDB 131, Cassandra 94, SQL Server 13, MySQL 16, core 62 —
including lost-race writes throwing ConcurrencyConflictException, TTLs read back from
system_schema, trigram indexes in pg_indexes, and document-shape ground truth via raw JSON/BSON.
Compatibility: no breaking changes. Requires eQuantic.Core.DataModel 4.0.0 /
eQuantic.Core.Domain 4.0.0 (as since v6.0.0).