Mapping
Ask for a type, get instances back.
public record Album(int Id, string Title);
List<Album> albums = GetAlbums.Query<List<Album>>(cnn);
Any class, record, or struct works. The engine matches the result columns to a constructor, a factory, or settable members, by name and type. No attributes, no base class, no configuration for the common case.
Flat rows map onto nested shapes. Columns prefixed with a member's name fill that member.
public record Artist(int Id, string Name) : IDbReadable;
public record Album(int Id, string Title, Artist Artist);
// Columns: Id | Title | ArtistId | ArtistName
List<Album> albums = GetAlbums.Query<List<Album>>(cnn);
// albums[0].Artist.Name is filled from ArtistName
There is one rule to know up front. A type you query directly is known automatically. A type reached only through another one must be registered. The IDbReadable marker on Artist above is the simplest way. Details on registration.
The engine is one negotiation composed of small parts, each a default implementation that can be swapped. The behaviors in this section, from nesting to tuples, are arrangements of those parts.
In this section
- Objects and nesting. Constructors, factories, members, prefixes, recursion.
- Nullability. What a
NULLcolumn does, and how to change it. - DynaObject. Rows without a fixed type.
- Registration. How a type becomes known, and which rules it signs up for.
- Construction paths. How paths are ordered, added, and reordered.
- Names. The matching rules and their adjustments.
- Reading order. Whether a slot holds the line or searches the schema.
- Parsers. How the parser for a
Tis picked, added, or driven directly.
The result wrappers (List<T>, Optional<T>, streaming) are on result shapes.