github linq2db/linq2db v6.5.0
Release 6.5.0

3 hours ago

Highlights of this release:

  • TimeSpan duration columns — declare the unit an integral column stores with [Duration(…)], and TimeSpan members, arithmetic and comparisons translate to SQL. Date differences now measure elapsed time instead of counting calendar boundaries (#5750)
  • Chained TablesInScopeHint calls now stack instead of silently dropping all but the innermost — .WithUpdLockInScope().WithRowLockInScope() emits both hints (#5850)
  • UpdateOptimisticWithRefresh refreshes the concurrency token on your entity after an optimistic update, so the same instance can be reused without re-reading the row (#5643)
  • IInterceptable is public again, so a custom IDataContext can receive interceptors — and a compiled query ending in ToList() / ToArray() now builds (#5813)
  • Table-per-hierarchy query compilation is back to 5.x speed, and no longer overflows the stack on large models (#5737)
  • Deep LoadWith chains and entities with many loaded associations build substantially faster on first execution (#5774)
  • ToListAsync() on a query with LoadWith (or a temp table, or a provider hint) now uses async ADO.NET instead of blocking a thread-pool thread, and Insert / Update / Delete / Merge no longer reject a LoadWith query (#5809)
  • A LoadWith filter closing over an optional value no longer serves the first closure state's results to every later call — a filtered call could return unfiltered rows, or an unfiltered call return nothing (#5801)
  • A custom Sql.Extension builder that reads an argument value no longer bakes it into the cached query — a second query with a different value silently ran the first one's SQL (#5841)
  • A repeated impure expression (counter.Next() twice in one predicate) no longer collapses into a single SQL parameter, which made the second occurrence filter on the first one's value (#5733)
  • joined != null ? joined.X : fallback inside a Union / Concat branch no longer drops its null check — non-matching rows came back as null or 0 instead of the fallback (#5831)
  • A set-operation branch whose projection mixes SQL and non-SQL parts ("p_" + id.ToString("N") inside a Concat) no longer fails the whole query (#5818)
  • Count() over a left join to a grouping with a computed key no longer crashes with "Cannot get field for …" — a paging query that worked for the page failed on the total (#5802)
  • Eager-loading an association off a GroupBy entity key now works — group d by d.Master into g … g.Key.Details.ToList() (#5727)
  • db.GetTable<Base>().Insert(() => new Derived { … }) on an inheritance-mapped table no longer throws "Property 'X' is not defined for type 'Base'" (#5840)
  • Updating through a DTO whose member is typed as a base type of the projected entity no longer fails with "Cannot find target table for UPDATE statement" (#5766)
  • A recursive CTE whose projection computes over its own columns no longer generates SQL the database rejects with a circular-reference error (#5764)
  • Sql.Window functions that reference no column — Sql.Window.Count(w => w) == 3 — now translate instead of throwing ServerSideOnlyException (#5783)
  • Remote contexts no longer leak a client per emulated InsertOrReplace / Upsert — visible on the gRPC and WCF transports, which open a channel per call (#5762)

Provider-specific highlights:

  • SQL Server / SAP HANA / MySQL — a constant ORDER BY inside a window function is no longer emitted verbatim: it errored on SQL Server and SAP HANA, and MySQL 8 read it as an output-column position and ordered by that column (#5817)
  • Oracle — bulk copy can send up to 6x fewer statements (64 KB → 384 KB SQL length limit), and BulkCopyOptions.MaxSqlLengthForBatch makes that limit configurable on any provider (#5828)
  • EF Core — one DbContext type used against two providers in the same process no longer shares a single mapping schema, which gave the second provider the first one's column names and types (#5780); and two servers of the same family in one process no longer share one cached provider when the context is configured with a DbDataSource or an external DbConnection (#5808)

linq2db.FSharp:

  • Join and Where predicates that capture an outer range variable now translate, and chained groupJoin … DefaultIfEmpty() emits real LEFT JOINs instead of dropping unmatched rows (#5701)

LINQPad driver:

  • macOS support on LINQPad 9, and database clients are provisioned per connection instead of all being installed with the driver — the driver also loads on LINQPad 8/9 without requiring the .NET 10 runtime (#5786)

Packaging:

  • Packages that carry a third-party binary — the T4 provider packages, linq2db.cli and the LINQPad 5 .lpx — now ship a THIRD-PARTY-NOTICES.txt (#5863)

Full release notes

Nugets

New Contributors

Full Changelog: v6.4.0...v6.5.0

Don't miss a new linq2db release

NewReleases is sending notifications on new releases.