Skip to content

Feature: Native AOT support via companion package DbConnectionPlus.Aot #13

Description

@rent-a-developer

Summary

DbConnectionPlus is currently not Native AOT compatible. Its mapping engine relies on runtime code generation (expression-tree .Compile() + MakeGenericMethod over value types, FastMember's Reflection.Emit, Fasterflect's DynamicMethod), all of which fail or warn under PublishAot=true. Under AOT, Query<T> (entities/value tuples), entity insert/update/delete, and temporary tables fail at runtime.

This request is to add AOT support via an opt-in companion package (DbConnectionPlus.Aot), following the Dapper → DapperAOT model, plus a small core change that makes untyped-row access AOT-safe by default.

Goals

  • Full feature parity off AOT. Every DbConnectionPlus feature must remain usable without the companion package and under a normal (JIT) runtime — this is the complete, unrestricted experience.
  • Maximum feature coverage on AOT. With the companion package referenced and opted in, as many features as possible must work under PublishAot=true - target: Query<T> (entities/value tuples/scalars), entity CRUD, and temporary tables.
  • No awkward tax on non-AOT consumers. AOT support must not push API changes that are cumbersome, weird, or surprising for people who never use AOT.

Requirements

  1. Companion NuGet package. Ship AOT support as a separate opt-in package (DbConnectionPlus.Aot) - a source generator that supplies reflection-free code paths for AOT consumers. Referencing it and adopting the required toolchain is opt-in; JIT-only users need neither.

  2. Non-generic query methods return DataRow instead of dynamic. Change the non-generic Query() / QueryFirst() / QuerySingle() / … overloads to return the statically-typed DataRow (a reflection-free type that is AOT-safe to produce). Its string indexer (row["Id"]) then works under AOT by default, with no cast. Dynamic member access (row.Id) stays available on the JIT as an explicit opt-in by assigning the result to dynamic. This is a breaking change, which is acceptable given the project's small consumer base.

  3. Breaking API changes are permitted where they help. Backward compatibility is not a hard constraint. Breaking changes are acceptable when they simplify the implementation or make AOT usage more convenient - provided they do not degrade the non-AOT experience (Goal 3) or remove features from the non-AOT path (Goal 1).

  4. Analyzer warnings for AOT-incompatible API usage. Provide build-time diagnostics that flag usage of API parts that cannot be made AOT-safe - in particular dynamic member access on a dynamic-typed row (row.Id), which is a DLR call site that no generator can fix. Diagnostics should steer AOT users toward the AOT-safe alternatives: Query<T>, or the DataRow string indexer (row["Id"]).

  5. Documentation of the dynamic opt-in. Update the README and the XML doc comments on the affected methods to explain that they now return DataRow, that row["Id"] is the recommended (and AOT-safe) access, and that dynamic member access requires opting in via dynamic row = ... (JIT-only).

Known bounds (documented, not in scope to fix)

  • Dynamic member access stays JIT-only by nature; it is surfaced via diagnostics and documentation, not made AOT-compatible.
  • End-to-end AOT is also gated by the ADO.NET provider: SQLite, MySQL, and PostgreSQL are viable; SQL Server works for the library's mainline paths (with provider caveats for Entra ID / Always Encrypted); Oracle remains blocked by its provider.

Acceptance criteria

  • All features remain available and behave correctly without the companion package on the JIT.
  • Non-generic query methods return DataRow; row["Id"] works under PublishAot=true with no cast, and dynamic row = ... still enables member access on the JIT.
  • With the companion package referenced and opted in, Query<T>, entity CRUD, and temporary tables succeed under PublishAot=true.
  • Building/publishing an AOT consumer produces actionable analyzer warnings for AOT-incompatible API usage.
  • README and XML doc comments document the DataRow return type, indexer access, and the dynamic opt-in.
  • Any API changes introduced for AOT impose no cumbersome or surprising burden on non-AOT consumers.

Metadata

Metadata

Labels

enhancementNew feature or request

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions