Highlights of this release:
- ⚠
TimeSpanduration columns — declare the unit an integral column stores with[Duration(…)], andTimeSpanmembers, arithmetic and comparisons translate to SQL. Date differences now measure elapsed time instead of counting calendar boundaries (#5750) - ⚠ Chained
TablesInScopeHintcalls now stack instead of silently dropping all but the innermost —.WithUpdLockInScope().WithRowLockInScope()emits both hints (#5850) UpdateOptimisticWithRefreshrefreshes the concurrency token on your entity after an optimistic update, so the same instance can be reused without re-reading the row (#5643)IInterceptableis public again, so a customIDataContextcan receive interceptors — and a compiled query ending inToList()/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
LoadWithchains and entities with many loaded associations build substantially faster on first execution (#5774) ToListAsync()on a query withLoadWith(or a temp table, or a provider hint) now uses async ADO.NET instead of blocking a thread-pool thread, andInsert/Update/Delete/Mergeno longer reject aLoadWithquery (#5809)- A
LoadWithfilter 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.Extensionbuilder 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 : fallbackinside aUnion/Concatbranch no longer drops its null check — non-matching rows came back asnullor0instead of the fallback (#5831)- A set-operation branch whose projection mixes SQL and non-SQL parts (
"p_" + id.ToString("N")inside aConcat) 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
GroupByentity 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.Windowfunctions that reference no column —Sql.Window.Count(w => w) == 3— now translate instead of throwingServerSideOnlyException(#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 BYinside 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.MaxSqlLengthForBatchmakes that limit configurable on any provider (#5828) - EF Core — one
DbContexttype 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 aDbDataSourceor an externalDbConnection(#5808)
linq2db.FSharp:
- Join and
Wherepredicates that capture an outer range variable now translate, and chainedgroupJoin … DefaultIfEmpty()emits realLEFT 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.cliand the LINQPad 5.lpx— now ship aTHIRD-PARTY-NOTICES.txt(#5863)
New Contributors
Full Changelog: v6.4.0...v6.5.0