Fixed result schema
public record Album(int Id, string Title);
public record AlbumSummary(int Id, string Title);
public record AlbumRow(int Id, string Title);
public static class AlbumCommands
{
public static DbCommand GetAlbum(DbConnection cnn, int albumId)
{
DbCommand command = cnn.CreateCommand();
command.CommandText = "SELECT AlbumId AS Id, Title FROM albums WHERE AlbumId = @albumId";
DbParameter parameter = command.CreateParameter();
parameter.ParameterName = "@albumId";
parameter.Value = albumId;
command.Parameters.Add(parameter);
return command;
}
}
Learn the schema from the first query
static readonly CachedTypeParser AlbumSchemaParser = new();
Album album = AlbumSchemaParser.Query<Album>(AlbumCommands.GetAlbum(cnn, 12));
AlbumSummary summary = AlbumSchemaParser.Query<AlbumSummary>(AlbumCommands.GetAlbum(cnn, 12));
The first query fixes the returned column schema. Each result type keeps its own parser against that schema.
bool learned = AlbumSchemaParser.HasSchema;
ColumnInfo[] columns = AlbumSchemaParser.Schema;
Supply the schema from a type
static readonly CachedTypeParser AlbumSchemaParser = CachedTypeParser.From<AlbumRow>();
The same schema can be passed directly.
static readonly CachedTypeParser AlbumSchemaParser = new(TypeSchema<AlbumRow>.Schema);
A runtime type can supply it too.
Type rowType = typeof(AlbumRow);
var albumSchemaParser = new CachedTypeParser(rowType);
AlbumRow describes the columns. It does not force the query result type.
Supply a reflected construction schema
public static class AlbumFactory
{
public static Album Create(int Id, string Title) => new(Id, Title);
}
static readonly MethodInfo CreateAlbumMethod = typeof(AlbumFactory).GetMethod(nameof(AlbumFactory.Create)) ?? throw new InvalidOperationException();
static readonly CachedTypeParser AlbumSchemaParser = new(SchemaExtractor.FromMethod(CreateAlbumMethod));
A constructor can be supplied directly.
static readonly ConstructorInfo AlbumRowConstructor = typeof(AlbumRow).GetConstructors()[0];
static readonly CachedTypeParser AlbumSchemaParser = new(AlbumRowConstructor);
Runtime result type
Type resultType = typeof(AlbumSummary);
using DbCommand command = AlbumCommands.GetAlbum(cnn, 12);
object? result = AlbumSchemaParser.Query(resultType, command, disposeCommand: false);
object? result = await AlbumSchemaParser.QueryAsync(resultType, command, disposeCommand: false, ct: cancellationToken);
Async stream
The fixed-schema parser can also stream rows asynchronously from an existing command.
using DbCommand command = AlbumCommands.GetAlbum(cnn, 12);
await foreach (Album album in AlbumSchemaParser.StreamQueryAsync<Album>(command, ct: cancellationToken))
Console.WriteLine(album.Title);
Get a parser without executing
ITypeParser<Album> albumParser = AlbumSchemaParser.Get<Album>();
ITypeParser runtimeParser = AlbumSchemaParser.Get(resultType);
Invalidate result parsers
AlbumSchemaParser.Invalidate<Album>();
AlbumSchemaParser.Invalidate();
The fixed column schema remains on the CachedTypeParser instance.