Skip to content

v5.7.0

Choose a tag to compare

@github-actions github-actions released this 22 Jul 13:12
· 42 commits to master since this release

5.7.0 (2026-07-22)

Three new native relational providers and a complex-query surface that works the same way across every store — typed, pushed down, and honest about cost.

Three new packages: PostgreSQL, MySQL, SQL Server

  • eQuantic.Core.Data.PostgreSql, eQuantic.Core.Data.MySql and eQuantic.Core.Data.SqlServer — the same contracts implemented directly on Npgsql, MySqlConnector and Microsoft.Data.SqlClient. No Entity Framework.
  • All three are thin dialects over the shared eQuantic.Core.Data.Relational engine: atomic batched commits (one DbBatch in a transaction), generated keys read back (RETURNING / OUTPUT INSERTED; MySQL rejects backfill honestly), explicit transactions with read-your-writes, native OR/!=/NULL pushdown with C# semantics preserved, native paging plus keyset continuation, computed set-based updates, global query filters, Explain(), and fluent typed migrations.
  • PostgreSQL arrays are first-class: = ANY, atomic append/remove, List<T> members.

Typed GroupBy with HAVING

var vips = await repo.GroupByAsync(
    x => x.Customer,
    g => new { g.Key, Orders = g.Count(), Revenue = g.Sum(x => x.Total) },
    having: g => g.Sum(x => x.Total) > 100m && g.Count() >= 2);
  • Native GROUP BY + HAVING on PostgreSQL/MySQL/SQL Server, a $group + $match pipeline on MongoDB, and a primary-key-restricted CQL GROUP BY on Cassandra — where CQL has no HAVING, the predicate's aggregates are computed on the cluster as extra select cells and filter the groups as they stream back; no extra rows travel.
  • Composite keys (x => new { x.A, x.B }), whole-key or per-member projection, anonymous or POCO shapes.
  • One portable contract: the same projection shapes are accepted — and the same ones rejected, with guidance — on every provider.

Typed UNION / UNION ALL

var feed = UnionQuery.All(
        Union.Of<Order>().Where(x => x.Status == "overdue")
            .Select(x => new { Name = x.Customer, Origin = "order" }),
        Union.Of<Buyer>().Select(x => new { x.Name, Origin = "buyer" }))
    .OrderBy(row => row.Name).Take(20);
var rows = await unitOfWork.UnionAsync(feed);
  • One statement on the relational providers, one $unionWith aggregation on MongoDB (UnionQuery.Distinct deduplicates with $group).
  • Branches combine different entities into a common shape, tag rows with per-branch constants, and keep each entity's global query filter applied per branch (IgnoringQueryFilters() opts a branch out) — a multi-tenant union stays tenant-scoped.
  • Ordering and paging apply to the combined result, on the store.

Aggregates everywhere

  • Min / Max / Average (IAggregateReadRepository<T>) now push down on all seven providers — SQL aggregates on the relational engine, CQL aggregates on Cassandra, $group single-group aggregations on MongoDB, VALUE MIN/MAX/AVG on Cosmos DB (partition-scoped when the filter pins the key).

Extensible database functions

  • Db.Like, Db.Year/Month/Day markers interpret inside any filter lambda — and carry real C# bodies, so an unmapped function degrades to the gated client-side residual instead of breaking.
  • Instance functions (ToLower, Trim, StartsWith/Contains as LIKE with dialect-neutral escaping) push down out of the box.
  • Bring your own: declare a static marker and map it per dialect with Functions.Map("Reversed", (column, args) => $"REVERSE({column})").

Fixes

  • Cassandra: the CQL renderer now refuses filter members that are not mapped columns (e.g. nested paths like x.Name.Length) — they run as gated client-side residual instead of producing invalid CQL.
  • Cassandra: timestamp cells materialize into DateTime members in grouped reads.

Also

  • FromSqlAsync escape hatch (relational) — arbitrary SQL materialized by column name.
  • Relational Include for reference and collection navigations (one follow-up IN query per path).
  • QueryFilters.FilterFor(Type, IServiceProvider) for runtime-typed resolution.

Everything validated against real servers: PostgreSQL, MySQL 8, SQL Server 2022, Cassandra 4.1, MongoDB replica set (Testcontainers) and the Cosmos DB Linux emulator in CI — 325 integration/unit tests locally plus the emulator suite.