Skip to content

Complete the async surface: async open, async memo reads, IAsyncEnumerable record streaming #297

Description

@chrisrichards

Context

#284 added true async record reading but deliberately deferred three pieces (listed in that PR):

  1. Async table openDbfTable's constructors read the header and column descriptors synchronously, so ExecuteReaderAsync still does a small synchronous read at open. Requires a static factory (DbfTable.OpenAsync(...)) since constructors cannot await; DbfDbCommand could then offer a genuinely async ExecuteDbDataReaderAsync.
  2. Async memo resolution — memo values are resolved during span parsing via a synchronous BinaryReader (DbfMemo), so a table with memo columns performs sync I/O inside ReadAsync. Needs the memo subsystem moved off BinaryReader onto buffered reads with async variants, and a way for value parsing to defer memo fetches (e.g. parse block pointers, resolve lazily/asynchronously on access).
  3. IAsyncEnumerable<DbfRecord> on DbfTable — parked on a real design question: yielding the mutated reused record is a footgun (ToListAsync would produce N references to one object), yielding fresh records allocates the full value-object set per row. The typed builder (Add typed queries: DbfQuery<T> builder and Dapper-style Query<T> (SQL support phase 5) #290) sidesteps this with materialised Ts; a raw-record async stream should probably yield fresh records and document the cost, or take the reused record as a parameter like Read(DbfRecord) does.

These fit naturally as one PR or three small ones.

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions