Net.Code.ADONet
7.1.0
dotnet add package Net.Code.ADONet --version 7.1.0
NuGet\Install-Package Net.Code.ADONet -Version 7.1.0
<PackageReference Include="Net.Code.ADONet" Version="7.1.0" />
<PackageVersion Include="Net.Code.ADONet" Version="7.1.0" />
<PackageReference Include="Net.Code.ADONet" />
paket add Net.Code.ADONet --version 7.1.0
#r "nuget: Net.Code.ADONet, 7.1.0"
#:package Net.Code.ADONet@7.1.0
#addin nuget:?package=Net.Code.ADONet&version=7.1.0
#tool nuget:?package=Net.Code.ADONet&version=7.1.0
YaDal - yet another data access layer
In a nutshell, this library is
- a light-weight Fluent API for ADO.Net
- small enough
- designed to help you get rid of the DBNull.Value mess, as well as the overall ADO.Net cruft
- NOT an ORM
Install it from NuGet: dotnet add package Net.Code.ADONet
Quick start
// from a connection string and provider factory...
await using var db = new Db(connectionString, SqlClientFactory.Instance);
// ...or (.NET 8+) from a DbDataSource; the Db does not own the data source, so dispose it yourself
// (typically it is a singleton): await using var dataSource = NpgsqlDataSource.Create(connectionString);
// await using var db = new Db(dataSource);
// map rows to objects (by column name; [Column] overrides it)
var adults = await db.Sql("SELECT * FROM Person WHERE Age >= @age")
.WithParameters(new { age = 18 })
.AsEnumerableAsync<Person>(cancellationToken)
.ToListAsync(cancellationToken);
// scalars, non-queries, explicit parameter types, timeouts
var count = await db.Sql("SELECT COUNT(*) FROM Person").AsScalarAsync<int>(cancellationToken);
await db.Sql("UPDATE Person SET Name = @name WHERE Id = @id")
.WithParameter("name", "Jane", DbType.String, size: 100)
.WithParameter("id", 42)
.WithTimeout(TimeSpan.FromSeconds(30))
.AsNonQueryAsync(cancellationToken);
// simple CRUD (table/column names follow the database's mapping convention);
// sent in batches when the provider supports DbBatch (e.g. SqlClient, Npgsql; not with Oracle)
await db.InsertAsync(people, cancellationToken);
var person = await db.SelectOneAsync<Person>(42, cancellationToken);
All async methods accept a CancellationToken. A Db wraps a single connection that is opened when the
first command executes; it is not thread-safe, so create one per unit of work and rely on connection pooling.
Source generated mappers (AOT-friendly)
Mark a type with [MapFromDataRecord] to generate a mapper (ProductMapper.ToProduct(IDataRecord)) at compile time:
[MapFromDataRecord]
public partial record Product(int Id, string Name, decimal Price);
var products = db.Sql("SELECT Id, Name, Price FROM Product").AsEnumerable(ProductMapper.ToProduct).ToList();
The reflection-based mapping (AsEnumerable<T>(), WithParameters(object), the CRUD helpers) and the
dynamic APIs are annotated as not trimming/AOT compatible; the generated mappers are.
For more information and examples, see the wiki.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- Microsoft.Data.SqlClient (>= 7.1.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- System.ComponentModel.Annotations (>= 5.0.0)
- System.Security.Cryptography.Pkcs (>= 10.0.14)
-
net8.0
- Microsoft.Data.SqlClient (>= 7.1.1)
- Microsoft.Extensions.Logging.Abstractions (>= 10.0.14)
- System.Security.Cryptography.Pkcs (>= 10.0.14)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 7.1.0 | 44 | 11/5/2026 |
| 7.0.0 | 78 | 11/4/2026 |
| 6.0.0 | 809 | 11/17/2024 |
| 6.0.0-preview.1 | 1,058 | 8/2/2023 |
| 5.0.1 | 13,940 | 3/4/2022 |
| 5.0.0 | 354 | 3/4/2022 |
| 5.0.0-preview.6 | 402 | 9/12/2021 |
| 5.0.0-preview.4 | 870 | 9/3/2021 |
| 5.0.0-preview.3 | 339 | 8/12/2021 |
| 5.0.0-preview.2 | 480 | 11/3/2020 |
| 5.0.0-preview.1 | 407 | 11/3/2020 |
| 4.0.73 | 5,581 | 11/4/2019 |
| 4.0.70 | 1,226 | 10/17/2019 |
| 4.0.55 | 851 | 10/9/2019 |
| 4.0.2 | 5,336 | 8/30/2018 |
| 4.0.1 | 1,165 | 8/29/2018 |
| 4.0.0-preview.1 | 453 | 11/2/2020 |
| 3.0.54 | 1,834 | 6/25/2018 |
| 3.0.51 | 2,257 | 2/1/2017 |
| 3.0.50 | 1,488 | 1/27/2017 |
7.1.0
Binary compatible with 7.0.0 (verified with package validation).
New:
- CancellationToken overloads for all async methods; IAsyncEnumerable results also honour WithCancellation.
- Db(DbDataSource) constructors (.NET 8+), e.g. new Db(NpgsqlDataSource.Create(...)).
- AsReaderAsync() returning a DbDataReader; AsEnumerableAsync(Func<IDataRecord, T>).
- WithParameter(name, value, DbType, size) for explicitly typed parameters.
- Insert/Update/Delete use DbBatch when the provider supports it (e.g. SqlClient, Npgsql): one round trip per 100 rows. Only with the built-in Default, PostGreSQL and DB2 configurations; Oracle, or a custom DbConfig with a prepare action, still executes row by row.
- BulkCopy/BulkCopyAsync overloads that take a SqlTransaction.
- Trimming/AOT annotations: reflection-based mapping and the 'dynamic' APIs are marked [RequiresUnreferencedCode]/[RequiresDynamicCode]; source generated mappers are AOT-safe.
Changed:
- Commands no longer open the connection when they are created, but when they are executed (asynchronously for async methods).
- Column to property mapping falls back to a case-insensitive match (an exact match still wins), consistent with constructor mapping and generated mappers.
- BulkCopy uses the Db's own connection instead of opening a second one. If a transaction is active on that connection, pass it to BulkCopy.
- Async commands log their parameters, like synchronous commands (at Trace level).
- With batching, Npgsql runs each batch in an implicit transaction: a failing row rolls back the rows of the same batch.
- Removed the dependencies on System.Linq.Async (conflicts with .NET 10's System.Linq.AsyncEnumerable), Microsoft.CSharp and Microsoft.Bcl.AsyncInterfaces. If your code used async LINQ operators (ToListAsync, ...) through this package, reference System.Linq.AsyncEnumerable (or use .NET 10+).
Fixed:
- BulkCopy failed with 'Login failed' after the Db's connection was opened (SqlClient removes the password from ConnectionString unless Persist Security Info=true).
- WithTimeout rounded sub-second timeouts down to 0, which means 'no timeout'.
- WithParameters threw KeyNotFoundException for types with an indexer or a property without a public getter (also in the CRUD helpers and ToDataTable).
- Insert bound the database-generated key as an extra parameter, which Oracle (BindByName) rejects; Delete bound all properties instead of only the key.
7.0.0
Breaking:
- Depends on Microsoft.Data.SqlClient 7. Entra ID (Azure AD) authentication now requires referencing Microsoft.Data.SqlClient.Extensions.Azure in your application.
New:
- net8.0 target (in addition to netstandard2.1).
- DateOnly/TimeOnly support, including Npgsql 10, which returns DateOnly/TimeOnly for date/time columns.
- IDataRecord extensions: GetDateOnly, GetTimeOnly, GetTimeSpan, GetDateTimeOffset, GetByteArray, GetEnum.
- Source generator: DateOnly, TimeOnly, TimeSpan, DateTimeOffset, byte[] and enum properties; error ADONET001 for unsupported property types.
Fixed:
- Mapping a type with a public property with a non-public setter or getter threw NullReferenceException.
- Generated mappers cached column ordinals across queries and did not map DBNull to null for nullable reference types.
- Record constructor mapping conversions, enum conversion, SelectOne key handling, WithParameters with runtime types, chunked GetBytes/GetChars, thread-safety of the query cache.
- Patched vulnerable transitive dependencies (System.Security.Cryptography.Pkcs, Microsoft.Bcl.Memory).