Introduction
AdoNet.Async is an async-first interface and base-class library for ADO.NET. It provides drop-in async wrappers for System.Data types, bringing modern async/await, IAsyncEnumerable, ValueTask, and async event support to the entire ADO.NET programming model.
The problem
System.Data was designed in the .NET Framework era. While DbConnection and DbDataReader eventually gained a handful of Task-returning methods, the core interfaces (IDbConnection, IDbCommand, IDataReader, IDataRecord) remain fully synchronous. This means:
- No async interfaces -- You cannot program against an async abstraction.
IDbConnection.Open()is synchronous; only the concreteDbConnection.OpenAsync()is available, and it returnsTask, notValueTask. - No
IAsyncEnumerable-- Iterating rows requires a manualwhile (reader.Read())loop. There is no way toawait foreachover a result set. - No async events --
DataTableevents likeRowChangingandColumnChangeduse synchronous delegates. If your handler needs to call an async API (validation service, audit log, cache invalidation), you are forced into sync-over-async or fire-and-forget patterns. - No
ValueTask-- The few async methods that exist returnTask/Task<T>, which allocates on every call even when the operation completes synchronously.
The solution
AdoNet.Async defines a complete set of async interfaces (IAsyncDbConnection, IAsyncDbCommand, IAsyncDataReader, IAsyncDataRecord, IAsyncDbTransaction) that mirror System.Data but add:
ValueTaskeverywhere -- Every async method returnsValueTaskorValueTask<T>for zero-allocation on synchronous completion paths.IAsyncEnumerable<IAsyncDataRecord>--IAsyncDataReaderimplementsIAsyncEnumerable, so you can stream rows withawait foreach.- Dual sync/async -- Every interface exposes both synchronous and asynchronous members, enabling gradual migration without breaking existing code.
- Async events --
AsyncDataTableexposes 9 async events (column changing/changed, row changing/changed/deleting/deleted, table clearing/cleared, table new row) powered byZeroAlloc.AsyncEventsfor zero-allocation, sequential dispatch. - Adapter pattern -- Existing
DbConnection/DbCommand/DbDataReaderinstances are wrapped with a single.AsAsync()call. No provider-specific code needed.
Packages
AdoNet.Async is split into six focused packages so you only take dependencies you need:
| Package | What it provides |
|---|---|
| AdoNet.Async | Core async interfaces (IAsyncDbConnection, IAsyncDbCommand, IAsyncDataReader, etc.) and abstract base classes. Zero external dependencies. |
| AdoNet.Async.Adapters | Adapter wrappers (AdapterDbConnection, AdapterDbCommand, etc.), the .AsAsync() extension method, and DI registration via AddAsyncData(). |
| AdoNet.Async.DataSet | AsyncDataTable, AsyncDataSet, AsyncDataRow, AsyncDataRowCollection, AsyncDataAdapter, and 9 async events. |
| AdoNet.Async.DataSet.Generator | Roslyn source generator that produces strongly typed async DataSet/DataTable/DataRow classes from .xsd schema files. |
| AdoNet.Async.Serialization.NewtonsoftJson | AsyncDataTableConverter and AsyncDataSetConverter for Newtonsoft.Json, wire-compatible with Json.Net.DataSetConverters. |
| AdoNet.Async.Serialization.SystemTextJson | AsyncDataTableJsonConverter and AsyncDataSetJsonConverter for System.Text.Json, producing the same wire format as the Newtonsoft package. |
Who is this for?
- Teams migrating existing ADO.NET code -- Wrap your existing
DbConnectionwith.AsAsync()and start using async interfaces immediately. Sync methods still work, so you can migrate incrementally. - New projects wanting async-first data access -- Program against
IAsyncDbConnectionandIAsyncDbCommandfrom day one. Use dependency injection withIAsyncDbProviderFactoryfor clean abstractions. - Applications using
DataTable/DataSet-- If your codebase relies onDataTablefor in-memory data manipulation,AsyncDataTablegives you async mutations, async events, andawait foreachiteration while keeping full interop with the underlyingDataTable. - Blazor WebAssembly developers -- The library is WASM-safe: sync methods throw
PlatformNotSupportedExceptionon the browser platform, guiding you toward the async path.
Next steps
- Installation -- Install the packages you need
- Quick Start -- See a complete working example
- Async Interfaces -- Understand the interface hierarchy
- Await ForEach -- Stream rows with
IAsyncEnumerable - Async DataTable -- Work with in-memory data asynchronously
- Async Events -- Subscribe to async mutation events
- Sync Bridge -- Understand when sync methods are safe to use