ZeroAlloc.ORM.Abstractions 0.2.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package ZeroAlloc.ORM.Abstractions --version 0.2.0
                    
NuGet\Install-Package ZeroAlloc.ORM.Abstractions -Version 0.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ZeroAlloc.ORM.Abstractions" Version="0.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ZeroAlloc.ORM.Abstractions" Version="0.2.0" />
                    
Directory.Packages.props
<PackageReference Include="ZeroAlloc.ORM.Abstractions" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ZeroAlloc.ORM.Abstractions --version 0.2.0
                    
#r "nuget: ZeroAlloc.ORM.Abstractions, 0.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ZeroAlloc.ORM.Abstractions@0.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ZeroAlloc.ORM.Abstractions&version=0.2.0
                    
Install as a Cake Addin
#tool nuget:?package=ZeroAlloc.ORM.Abstractions&version=0.2.0
                    
Install as a Cake Tool

<h1 align="center">ZeroAlloc.ORM</h1>

<p align="center">Source-generator-based, NativeAOT-clean raw-SQL data access for .NET. Annotate <code>partial</code> methods with <code>[Query]</code> / <code>[Command]</code> / <code>[StoredProcedure]</code>; the generator emits typed parameter binding + materialization against <a href="https://github.com/MarcelRoozekrans/AdoNet.Async">AdoNet.Async</a>. Zero runtime reflection.</p>

Status: Pre-release. v0.1 milestone in progress. Authoritative design lives at docs/design/2026-05-30-v1.0-design.md. Working backlog at docs/plans/za-orm-backlog.md.

What it is

A source-generator-driven data-access library that fills in the gap between two extremes adopters currently choose from:

  • EF Core — full LINQ-to-SQL ORM, but its precompile-queries pipeline currently collides with co-resident source generators (e.g. ZA.Rest), blocking NativeAOT publish in template stacks like ZeroAlloc.Templates.
  • Hand-written ADO.NET — works under AOT, but every repository becomes a hand-shaped tower of CreateCommand / CreateParameter / ReadAsync calls.

ZeroAlloc.ORM is the middle path: write the SQL string in an attribute, declare the partial method signature, let the source generator emit the ADO.NET pipeline. Zero runtime reflection, fully AOT-publishable, idiomatic with the rest of the ZeroAlloc ecosystem (consumes AdoNet.Async, dogfoods ZeroAlloc.ValueObjects, shares the convention catalog with ZeroAlloc.Mapping).

Packages

Package Description NativeAOT
ZeroAlloc.ORM Runtime helpers + ActivitySource for observability. Depends on AdoNet.Async.
ZeroAlloc.ORM.Abstractions Public attribute surface ([Query], [Param], [StoreAsString]) + exception types. Remaining attributes ([Command], [StoredProcedure], [Materialize]) land in their implementing milestones (v0.4–v0.5).
ZeroAlloc.ORM.Generator Roslyn incremental source generator. Build-time only. N/A
ZeroAlloc.TypeConversions Shared convention-discovery catalog (value-objects, enums, composites). Build-time only. N/A

Quick Start

Scalar query

using System.Data.Async;
using System.Threading;
using System.Threading.Tasks;
using ZeroAlloc.ORM;

public sealed partial class Repo(IAsyncDbConnection connection)
{
    [Query("SELECT count(*) FROM Orders")]
    public partial Task<int> CountOrdersAsync(CancellationToken ct);
}

The source generator emits the open / execute / close pipeline against AdoNet.Async's IAsyncDbConnection. Zero runtime reflection; the emit composes through global::-qualified identifiers so it doesn't care about the consumer's using directives.

Row materialization (FlatRow)

public sealed record OrderRow(int Id, int CustomerId, decimal Total);

public sealed partial class OrderRepo(IAsyncDbConnection connection)
{
    [Query("SELECT Id, CustomerId, Total FROM Orders WHERE Id = @id")]
    public partial Task<OrderRow?> GetByIdAsync(int id, CancellationToken ct);
}

Positional record + matching SELECT column order = no mapping config. Nullable return = empty result set yields null.

Available in v0.1

  • [Query] with scalar (Task<int>, Task<T?>) and FlatRow (Task<TRow?>) return shapes.
  • 14 primitive types in parameter binding (int / long / short / byte / bool / decimal / double / float / string / Guid / DateTime / DateTimeOffset / TimeSpan / byte[]) + nullable variants.
  • [Param(Name = "...")] SQL-side parameter name override.
  • Compile-time diagnostics (ZAO001–ZAO009 + informational ZAO020–ZAO022) for signature contract violations.
  • NativeAOT-clean publish (verified by aot-smoke CI gate).

Added in v0.2

  • Value-object columns — types annotated with [ValueObject] from ZeroAlloc.ValueObjects (with a static From factory and a Value property) bind through their underlying primitive. Parameters unwrap to Value; reads wrap via T.From(primitive).

    [ValueObject]
    public readonly partial struct CustomerId
    {
        public int Value { get; }
        public CustomerId(int value) { Value = value; }
        public static CustomerId From(int value) => new(value);
    }
    
    public sealed record CustomerRow(CustomerId Id, string Name);
    
    public sealed partial class CustomerRepo(IAsyncDbConnection connection)
    {
        [Query("SELECT Id, Name FROM Customers WHERE Id = @id")]
        public partial Task<CustomerRow?> GetAsync(CustomerId id, CancellationToken ct);
    }
    
  • Enums (default int round-trip) — any enum parameter or column binds as its underlying integer (reader.GetInt32 + cast on read; cast to underlying primitive on bind).

  • Enums (string round-trip) — annotate the enum type with [StoreAsString] to round-trip as the member name (reader.GetString + Enum.Parse<T> on read; member-name bind).

  • Domain-entity classes — plain class types with a single multi-arg public ctor materialize via column-name-keyed reads (__reader.GetOrdinal("ColumnName")). SELECT column order is irrelevant; each ctor parameter resolves to its matching column by name. Records keep the positional FlatRow path.

  • Single-arg record discovery + static From factory discovery — wrappers without [ValueObject] still resolve when ConventionDiscovery can find an obvious construction strategy.

  • New diagnostics ZAO040–ZAO044 — materialization-side failures (no construction strategy, conflicting strategies, unresolved ctor parameters, etc.) surface at build time with focused messages.

Deferred to later milestones: [Command] / [StoredProcedure] (v0.4), IAsyncEnumerable<T> streaming (v0.3), multi-result-set tuples (v0.3), multi-column composite types (v0.5).

Design + roadmap

License

MIT

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on ZeroAlloc.ORM.Abstractions:

Package Downloads
ZeroAlloc.ORM

Source-generator-based, NativeAOT-clean raw-SQL data access for .NET. Annotate partial methods with [Query]; the generator emits typed parameter binding + materialization against AdoNet.Async's IAsyncDbConnection. Zero runtime reflection.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.6.0 528 6/4/2026
1.5.0 614 6/3/2026
1.4.0 109 6/3/2026
1.3.0 102 6/3/2026
1.2.0 328 6/2/2026
1.1.0 186 6/1/2026
1.0.0 112 6/1/2026
0.7.0 113 6/1/2026
0.6.0 110 6/1/2026
0.5.0 116 5/31/2026
0.4.0 121 5/31/2026
0.3.0 106 5/31/2026
0.2.0 114 5/30/2026
0.1.0 111 5/30/2026