Whats New in v4 - lobodava/artisan-orm GitHub Wiki

Artisan.Orm 4.0 is a multi-targeting refresh of the library. Most API additions are additive, but check target-framework compatibility and the configuration changes below when migrating an older application. The subsequent fixes and migration guidance are documented in Preparing for 4.1.0.

Targets

  • netstandard2.1 — compatible .NET Standard 2.1 consumers, including .NET 6 and .NET 7
  • net8.0 — .NET 8 and later compatible consumers
  • net10.0 — .NET 10 and later compatible consumers

A .NET 6/7 application cannot reference the net8.0 assembly; it uses the compatible netstandard2.1 asset. .NET Framework does not support .NET Standard 2.1; applications remaining on .NET Framework need the older compatible package line (2.x).

DateOnly / TimeOnly and System.Text.Json-based JSON parameters are gated behind #if NET6_0_OR_GREATER and only available on the net8.0 / net10.0 targets.

Configuration changes

  • The library no longer reads Web.config / App.config automatically. Pass the connection string explicitly to the RepositoryBase constructor — see About Connection Strings.

  • Nullable reference types are enabled. Public APIs that may return null now annotate it (User?, string?, etc.). Custom repositories that override or call these methods may surface CS86xx warnings until callers add ? annotations. No runtime behavior change.

New APIs

Bulk insert

SqlConnection.BulkCopy<T> / BulkCopyAs<T> and matching wrappers on RepositoryBase — sync and async, with CancellationToken. See BulkCopy.

Multi-result-set tuple reads

ReadToLists<T1, T2> / <T1, T2, T3> / <T1, T2, T3, T4> returning a typed tuple of lists from a single procedure with multiple select statements. See ReadToLists.

Pair them with MergeJoin to assemble parent / child object graphs from a single round-trip without a GroupJoin Dictionary allocation. See MergeJoin.

Streaming with IAsyncEnumerable

ReadToAsyncEnumerable<T> / ReadAsAsyncEnumerable<T> — for queries that return more rows than you want to buffer, stream them one at a time with cancellation support. See Streaming with IAsyncEnumerable.

JSON parameters (NET6+)

AddJsonParam<T>(name, value) — serialises a CLR object to JSON and binds it to an nvarchar(max) parameter for parsing on the SQL side via OPENJSON.

DateOnly / TimeOnly parameters and reads (NET6+)

  • AddDateParam(DateOnly) / AddTimeParam(TimeOnly) — both nullable variants
  • dr.GetDateOnly(...) / dr.GetTimeOnly(...) — with nullable and default-value overloads

Output parameters

Nine new typed helpers — AddBitOutputParam, AddTinyIntOutputParam, AddSmallIntOutputParam, AddIntOutputParam, AddBigIntOutputParam, AddDecimalOutputParam(name, precision, scale), AddGuidOutputParam, AddDateTime2OutputParam, AddDateTimeOffsetOutputParam. Read the values back via cmd.Parameters[name].Value after ExecuteNonQuery.

Default-value reader extensions

Eleven new Get* overloads with a defaultValue argument — GetByte(ord, default), GetInt32(ord, default), GetString(ord, default), GetDateTime(ord, default), etc. — for "if NULL, fall back to this".

Pre-populated lists

ReadToList<T>(sql, IList<T>? list, ...) and ReadAsList<T>(...) overloads — append fetched rows to an existing list instead of allocating a new one. Useful when assembling results from multiple queries into a single collection.

Async transactions

BeginTransactionAsync / RunInTransactionAsync — both with optional IsolationLevel and CancellationToken. See Transactions.

Async-symmetry methods

Async siblings added for previously sync-only APIs: ReadToTreeAsync, ReadToTreeListAsync, ReadToArrayAsync, ReadAsArrayAsync, ReadDynamicAsync, ReadDynamicListAsync, ReadDynamicArrayAsync, ReadToObjectRowAsync / ReadToObjectRowsAsync, plus ExecuteAsync(sql, CancellationToken, params) overload.

Bug fixes

  • RecordTypeMapper.CreateObject(SqlDataReader) standalone wrapper — was reading the wrong column ordinal when called outside a parent mapper context. Fixed.
  • ExecuteCommandAsync — fixed sync-over-async issue in the connection close path that could deadlock under tight ASP.NET Core thread-pool pressure.

Dependency updates in the initial v4 refresh

The initial v4 refresh used Microsoft.Data.SqlClient 7.0.1 and an explicit Microsoft.SourceLink.GitHub 10.0.203 reference. The current working tree has subsequent changes below; consult the package actually installed when reproducing an older release.

Changes being prepared for 4.1.0

The complete 4.1.0 overview covers corrected read factories, external transaction ownership, cache isolation, sample hierarchy SQL, and graph-ordering/deadlock guidance. The updates are recorded in the 4.1.0 section of CHANGELOG.md. They are not a claim that an already downloaded v4 package includes them.

  • A repository Claude Code skill provides guidance and examples for applications using Artisan.Orm. It targets the planned 4.1.0 contract and includes verification scenarios.
  • trimToNull now applies its returned value in all four variable-length string parameter helpers. Sized helpers also apply truncate; trimming precedes truncation or length validation. See AddParam extensions.
  • CheckForDataReplyException accepts an explicit Ok status and advances directly to payload. See DataReply.
  • Mapper requirements are also checked by the bundled Roslyn analyzer (ART001–ART007). Its compiler host needs Roslyn 4.8 or later; runtime checks remain. AllMain now requires CreateObject, CreateDataTable, and CreateDataRow consistently. See RequiredMethod and compile-time mapper validation (Roslyn).
  • Microsoft.Data.SqlClient is updated to 7.1.1, vulnerable PKCS dependencies are patched, and SourceLink is supplied by the .NET SDK instead of an explicit SourceLink package. Current build versions are specified in the project files and global.json.

See also:

⚠️ **GitHub.com Fallback** ⚠️