v5.8.0
5.8.0 (2026-07-22)
The release that turns the providers into a modeled, enterprise-grade data layer: one store-neutral modeling vocabulary, lifecycle and concurrency semantics, value converters, live-schema evolution, and more native query surface — validated against seven real stores.
Store-neutral modeling — one vocabulary for every provider
- eQuantic-owned annotations interpreted by all seven providers — no driver attributes on entities (
[BsonElement], EF's[Column]), no rewrite when an entity moves between stores, names that never clash withSystem.ComponentModel.DataAnnotations:[Entity],[EntityKey],[StoredAs],[Unmapped],[PartitionKey],[ClusteringKey],[ConcurrencyToken],[Counter],[SearchIndex],[TimeToLive]. - Explicit precedence:
conventions < annotations < fluent. Each provider honours the subset that maps to its store and ignores the rest. - The model never lies:
model.Explain(dialect)reports every mapping decision — names, stored types, keys, tokens, converters, navigations, lifecycle — the wayExplain()reports a query.
Enterprise write semantics
- Entity lifecycle by convention (
eQuantic.Core.Domain/eQuantic.Core.DataModel):CreatedAt/UpdatedAtstamped on every provider (set-based updates included), andIEntityTimeEndeddeletes become soft deletes with an automatic live-rows filter on reads and set-based writes. DataConventionsto tune it:Clock(aTimeProvider— deterministic in tests),LifecycleStamps/SoftDeletetoggles, andCurrentUserId— a per-request accessor that also stamps the who (CreatedById/UpdatedById/DeletedById, the DataModel shapes) by property-name convention.- Optimistic concurrency:
ConcurrencyToken(x => x.Version)on the relational model matches and bumps the token on every write; a commit that misses rows throwsConcurrencyConflictExceptionand rolls back. Cosmos does the same viaConcurrencyToken(x => x.ETag)(If-Match). - Value converters (relational):
.Converts(x => x.Email, e => e.Value, EmailAddress.Create)maps Value Objects and enums-as-strings to stored scalars at every boundary — DDL, inserts/updates, filters, materialization. The domain type never reaches the driver.
More native query surface
- jsonb document columns (PostgreSQL): scalar-keyed dictionaries map to
jsonb;ContainsKey→?, the indexer →->>. - SASI
LIKEpushdown (Cassandra): a[SearchIndex]/SearchIndex(...)column servesStartsWith/EndsWith/ContainsandDb.Likeas nativeLIKE— the migration creates the index. - MariaDB dialect:
AddMariaDbDatabase(...)— the MySQL engine and driver plusINSERT … RETURNING, so generated keys read back (which the MySQL dialect honestly rejects).
Richer fluent migrations
- Live-schema evolution:
AddField/DropField(ALTER TABLE ADD/DROP COLUMN; document stores gain fields on write,$unseton Mongo). - Rich index options: typed partial/filtered indexes (
o.Filtered(x => ...), the predicate interpreted like a query filter), PostgreSQLGIN, MongoDBtextand TTL — each rejected with guidance where a store can't build it.
Declared navigations & resilience
Reference(...)/Collection(...)override the FK conventions for legacy schemas, and dotted include paths (Include("Invoices.Order")) load level by level — oneINquery per segment.- Transient-fault retries (relational, opt-in):
AddRelationalResilience(...)— reads retry automatically, commits only behindRetryCommits, nothing retries inside an explicit transaction; transience comes from the driver (DbException.IsTransient). The document/wide-column drivers ship native retry and need none.
Grouped & aggregate reads (from 5.7, now provider-wide)
- Typed
GroupBywithHAVINGon the relational providers, MongoDB ($group) and Cassandra (primary-key CQLGROUP BY);Min/Max/Averagepush down on all seven. On Cosmos DB,GroupByis rejected honestly for now (the SDK's LINQ GroupBy emitsSELECT VALUE {…}, invalid withGROUP BY; group client-side there) — a hand-built Cosmos SQL GROUP BY is tracked for a follow-up.
Engineering
- The
eQuantic.Core.Data.Queryengine seam (interpreters + dialect-agnostic IR) is a declared provider SPI: public so third-party dialects can build on it, hidden from application IntelliSense ([EditorBrowsable(Never)]), versioned with the engine. - Cosmos testing moves to the vNext emulator: runs on ARM64 (Cosmos is now locally testable for the first time), gated on the
/readyhealth probe with a data-plane (pgcosmos) bootstrap retry — the chronic 408/503 CI collapses are gone.
Validated against real servers: PostgreSQL, MySQL 8, MariaDB, SQL Server 2022, Cassandra 4.1 (SASI enabled), MongoDB replica set (Testcontainers) and the Azure Cosmos DB vNext emulator — 350+ tests.