![]() |
VOOZH | about |
dotnet add package pengdows.crud --version 2.0.5
NuGet\Install-Package pengdows.crud -Version 2.0.5
<PackageReference Include="pengdows.crud" Version="2.0.5" />
<PackageVersion Include="pengdows.crud" Version="2.0.5" />Directory.Packages.props
<PackageReference Include="pengdows.crud" />Project file
paket add pengdows.crud --version 2.0.5
#r "nuget: pengdows.crud, 2.0.5"
#:package pengdows.crud@2.0.5
#addin nuget:?package=pengdows.crud&version=2.0.5Install as a Cake Addin
#tool nuget:?package=pengdows.crud&version=2.0.5Install as a Cake Tool
pengdows.crud is a SQL-first data access library for .NET 8+. It favors explicit SQL, inspectable command builders, and provider-aware execution over ORM-style query generation.
No LINQ. No tracking. No hidden unit of work.
DatabaseContext / IDatabaseContext for connection lifecycle, dialect behavior, quoting, parameter creation, metrics, and transactionsTableGateway<TEntity, TRowID> / ITableGateway<TEntity, TRowID> for row-id CRUD, business-key retrieval, batch operations, and async streamingPrimaryKeyTableGateway<TEntity> / IPrimaryKeyTableGateway<TEntity> for tables keyed only by [PrimaryKey] columnsISqlContainer for build-first SQL composition plus direct execution helpersITransactionContext for explicit commit, rollback, and savepoint controlBuildCreate, BuildRetrieve, BuildUpdateAsync, BuildDelete, BuildUpsertLoadSingleAsync, LoadListAsync, and LoadStreamAsyncCreateAsync, RetrieveOneAsync, RetrieveAsync, UpdateAsync, DeleteAsync, and UpsertAsyncDbDataSource support for shared prepared-statement caching (e.g., NpgsqlDataSource)[Version]IAuditValueResolverIDatabaseContext.Metrics and live updates via MetricsUpdatedDbMode strategies: Standard, KeepAlive, SingleWriter, SingleConnection, and BestDbException is translated to structured subtypes (ConcurrencyConflictException, UniqueConstraintViolationException, DeadlockException, etc.)The repository contains concrete support for:
When product detection cannot identify the connected database, the library falls back to a conservative SQL-92 dialect.
dotnet add package pengdows.crud
using Microsoft.Data.SqlClient;
using pengdows.crud;
var context = new DatabaseContext(
"Server=.;Database=app;Trusted_Connection=True;",
SqlClientFactory.Instance);
var gateway = new TableGateway<Order, long>(context);
bool created = await gateway.CreateAsync(new Order
{
Id = 42,
OrderNumber = "ORD-42"
});
var one = await gateway.RetrieveOneAsync(42L);
var many = await gateway.RetrieveAsync(new long[] { 42, 43 });
await using var tx = await context.BeginTransactionAsync();
await gateway.UpsertAsync(order, tx);
await tx.CommitAsync();
// Minimal: connection string + factory
var ctx = new DatabaseContext(connectionString, SqlClientFactory.Instance);
// With read-only replica
var ctx = new DatabaseContext(connectionString, SqlClientFactory.Instance,
readOnlyConnectionString: replicaConnectionString);
// Full configuration object (logger, pool sizes, prepare mode, etc.)
var ctx = new DatabaseContext(
new DatabaseContextConfiguration
{
ConnectionString = connectionString,
DbMode = DbMode.Standard,
ReadWriteMode = ReadWriteMode.ReadWrite,
ReadOnlyConnectionString = replicaConnectionString,
MaxConcurrentReads = 20,
MaxConcurrentWrites = 5
},
SqlClientFactory.Instance,
loggerFactory);
// Provider DbDataSource (PostgreSQL prepared-statement sharing)
var dataSource = NpgsqlDataSource.Create(connectionString);
var ctx = new DatabaseContext(configuration, dataSource, NpgsqlFactory.Instance);
[Id] is the row identifier used by row-id operations[PrimaryKey] is the business key and may be composite[Id] and [PrimaryKey] must not be placed on the same propertyPrimaryKeyTableGateway<TEntity> when the entity has no [Id] column at allRaw DbException from providers is automatically translated to a typed hierarchy:
DatabaseException (abstract — carries Database, SqlState, ErrorCode, ConstraintName, IsTransient)
├─ DatabaseOperationException
│ ├─ ConcurrencyConflictException ← [Version] column mismatch on UpdateAsync
│ ├─ CommandTimeoutException ← IsTransient = true
│ ├─ ConnectionException
│ ├─ TransactionException
│ ├─ TransientWriteConflictException ← IsTransient = true
│ │ ├─ DeadlockException
│ │ └─ SerializationConflictException
│ └─ ConstraintViolationException (abstract)
│ ├─ UniqueConstraintViolationException
│ ├─ ForeignKeyViolationException
│ ├─ NotNullViolationException
│ └─ CheckConstraintViolationException
├─ DataMappingException
└─ SqlGenerationException
Non-DatabaseException subtypes thrown by the infrastructure:
ModeContentionException : TimeoutException — SingleWriter/SingleConnection lock timed outPoolSaturatedException : TimeoutException — internal connection pool exhaustedPoolForbiddenException : InvalidOperationException — write attempted on read-only contextTransactionModeNotSupportedException : NotSupportedException — savepoint or read-only tx on unsupported dialectConnectionFailedException : Exception — startup connection failure (carries Phase and Role)try
{
await gateway.UpdateAsync(entity);
}
catch (ConcurrencyConflictException)
{
// [Version] mismatch — reload and retry
}
catch (UniqueConstraintViolationException ex)
{
// ex.ConstraintName identifies which constraint fired
}
catch (DatabaseException ex) when (ex.IsTransient == true)
{
// Deadlock, serialization failure, or timeout — safe to retry
}
Three distinct methods replace the ambiguous ExecuteScalarAsync from v1:
// Throws if no rows or value is null/DBNull and T is non-nullable
int count = await sc.ExecuteScalarRequiredAsync<int>();
// Returns null for both "no rows" and "DBNull value"
string? name = await sc.ExecuteScalarOrNullAsync<string>();
// Unambiguously distinguishes no-row, null, and value
ScalarResult<string> result = await sc.TryExecuteScalarAsync<string>();
if (result.Status == ScalarStatus.Value) { /* result.Value */ }
if (result.Status == ScalarStatus.Null) { /* row returned but value was NULL */ }
if (result.Status == ScalarStatus.None) { /* no rows returned */ }
If this library saves you time, consider buying me a coffee.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 net8.0 is compatible. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 is compatible. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
Showing the top 1 NuGet packages that depend on pengdows.crud:
| Package | Downloads |
|---|---|
|
pengdows.hangfire
SQL-first Hangfire job storage built on pengdows.crud — a strongly-typed, cross-database data access layer for .NET. |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.0.5 | 137 | 4/17/2026 |
| 2.0.4 | 202 | 3/31/2026 |
| 2.0.3 | 174 | 3/27/2026 |
| 2.0.2 | 108 | 3/24/2026 |
| 2.0.1 | 118 | 3/22/2026 |
| 2.0.0 | 180 | 2/28/2026 |
| 1.0.1769867481 | 182 | 1/31/2026 |
| 1.0.1769543242 | 125 | 1/27/2026 |
| 1.0.1769395132 | 127 | 1/26/2026 |
| 1.0.1769360331 | 118 | 1/25/2026 |
| 1.0.1767194225 | 142 | 12/31/2025 |
| 1.0.1759683344 | 199 | 10/5/2025 |
| 1.0.1759623120 | 190 | 10/5/2025 |
| 1.0.1756777911 | 222 | 9/2/2025 |
| 1.0.1756431873 | 250 | 8/29/2025 |
| 1.0.1756401895 | 246 | 8/28/2025 |
| 1.0.1756206653 | 286 | 8/26/2025 |
| 1.0.1756088498 | 280 | 8/25/2025 |
| 1.0.1755050805 | 213 | 8/13/2025 |
| 1.0.1754686097 | 203 | 8/8/2025 |