OmniDataAccess.Core
1.2.0
dotnet add package OmniDataAccess.Core --version 1.2.0
NuGet\Install-Package OmniDataAccess.Core -Version 1.2.0
<PackageReference Include="OmniDataAccess.Core" Version="1.2.0" />
<PackageVersion Include="OmniDataAccess.Core" Version="1.2.0" />
<PackageReference Include="OmniDataAccess.Core" />
paket add OmniDataAccess.Core --version 1.2.0
#r "nuget: OmniDataAccess.Core, 1.2.0"
#:package OmniDataAccess.Core@1.2.0
#addin nuget:?package=OmniDataAccess.Core&version=1.2.0
#tool nuget:?package=OmniDataAccess.Core&version=1.2.0
OmniDataAccess.Core
OmniDataAccess.Core contains the shared types, configuration classes, annotations and helpers used across all OmniDataAccess packages. It is intentionally minimal — focused on the small, well-tested building blocks that the SQL and NoSQL providers depend on.
📦 Installation
dotnet add package OmniDataAccess.Core
🧩 What's in this package
- Result types:
CacheResult<T>,DatabaseResult,PaginatedResult<T>,QueueResult<T> - Message queue types:
QueueMessage<T>(envelope returned by consume/read/claim),PendingMessageInfo(returned byGetPendingAsync) - Procedure metadata:
Procedure,ProcedureParameter(DDL — used byCreateProcedureAsync/CreateFunctionAsync),OmniParameter(execution — binds stored procedure calls, including OUTPUT/INPUT-OUTPUT parameters) - Exceptions:
DatabaseManagerException,DatabaseConnectionException,DatabaseConstraintViolationException,CacheManagerException,QueueManagerException,OmniConcurrencyException - Configuration:
DatabaseManagerOptions,CacheManagerOptions,MessageQueueOptions(extendsCacheManagerOptions) - Schema annotations:
[Table],[Column],[PrimaryKey],[UniqueKey],[NotMapped],[NotInserted],[NotUpdated],[SoftDelete],[HasMany],[HasOne],[BelongsTo],[CacheKey],[CacheExpiry],[RowVersion],[Index] - Core interfaces:
IDatabaseManager - ORM hooks:
IOmniHooks—BeforeCreate/AfterCreate/BeforeUpdate/AfterUpdate/BeforeDelete/AfterDeletelifecycle callbacks, called automatically byOmniDBwhen an entity implements it - Utilities:
JsonHelpers,Loggers,Generators
Configuration
DatabaseManagerOptions
var opts = new DatabaseManagerOptions
{
ConnectionString = "Host=localhost;Database=mydb;Username=me;Password=secret",
Database = "mydb",
ContextTimeout = 30, // command timeout in seconds
ShowLogs = true, // enables connection/retry diagnostic messages; timing logs always emit
VerifySsl = false,
UsePooling = true, // default; pooling is on by default for all providers
MinPoolSize = 0,
MaxPoolSize = 100,
ConnectionIdleLifetime = 300, // seconds
// Transient-error retry (exponential backoff)
RetryCount = 3, // attempts after the first failure
RetryDelayMs = 200, // base delay; doubles each attempt → 200ms, 400ms, 800ms
};
// Query-log redaction: parameter values matching a keyword (case-insensitive substring,
// ignoring underscores) are logged as "***REDACTED***" instead of their real value.
// Pre-populated with: password, passwd, pwd, hash, secret, token, pin, ssn, apikey,
// creditcard, cvv, authorization.
opts.AddSensitiveParameterNames("otp", "nationalid"); // add domain-specific keywords
opts.SensitiveParameterNames.Remove("token"); // drop a default causing false positives
Transient errors that trigger a retry: network timeouts, connection resets, deadlocks, serialisation failures, CockroachDB restart-transaction, Azure SQL resource-pool throttling, and any IOException / SocketException (including the Npgsql "Exception while reading from stream" error).
CacheManagerOptions
var cacheOpts = new CacheManagerOptions
{
ConnectionString = "localhost:6379",
DatabaseIndex = 0,
CacheExpiry = 3600, // seconds; -1 = no expiry
ShowLogs = true, // enables connection/reconnect diagnostic messages; timing logs always emit
};
MessageQueueOptions (extends CacheManagerOptions)
Configuration for IMessageQueueManager/IPubSubManager (implementations live in OmniDataAccess.NoSqlDatabases; this class is defined here since it's a config type, not a provider).
var queueOpts = new MessageQueueOptions("localhost:6379")
{
ConsumerGroup = "order-processors",
MaxDeliveryAttempts = 5, // informational only — the library does not auto-dead-letter
ClaimMinIdleTime = TimeSpan.FromSeconds(30),
StreamMaxLength = 10_000, // Redis: XADD MAXLEN ~ trim. MemCache: caps each group's channel. null = unbounded
MessageTtl = TimeSpan.FromHours(24), // age-based trim (exact, not approximate). null = no age-based trim
QueueTtl = TimeSpan.FromHours(1), // idle-queue expiration. null = never expires
DefaultReadCount = 10,
};
See the OmniDataAccess.NoSqlDatabases README for the full IMessageQueueManager/IPubSubManager API and every MessageQueueOptions field.
Result types
// CacheResult<T> — returned by all ICacheManager read operations
CacheResult<User> result = await cache.GetStringAsync<User>("user:1");
if (result.IsSuccess)
Console.WriteLine(result.Data?.Name);
else
Console.WriteLine(result.FailureReason); // CacheMiss | FailedConnection | InternalError
// DatabaseResult — returned by ExecuteAsync
DatabaseResult r = await db.ExecuteAsync("DELETE FROM sessions WHERE expired = true");
Console.WriteLine($"{r.RowsAffected} rows, took {r.ExecutionTime.TotalMilliseconds:F0}ms");
// PaginatedResult<T> — returned by FindPagedAsync
PaginatedResult<IEnumerable<User>> page = await db.FindPagedAsync<User>("SELECT * FROM users", page: 1, limit: 20);
Console.WriteLine($"Page {page.Page}, total {page.TotalCount}, has next: {page.HasNextPage}");
foreach (var u in page.Data) Console.WriteLine(u.Name);
// QueueResult<T> — returned by IMessageQueueManager read operations (ConsumeAsync, ReadAsync, ...)
QueueResult<QueueMessage<Order>> msg = await queue.ConsumeAsync<Order>("orders");
if (msg.IsSuccess)
Console.WriteLine(msg.Data?.Data);
else
Console.WriteLine(msg.FailureReason); // QueueEmpty | QueueNotFound | FailedConnection | InternalError | ...
Stored procedure OUTPUT parameters (OmniParameter)
Anonymous-object parameters (new { id = 1 }) are input-only — Dapper solves this with DynamicParameters; OmniDataAccess uses OmniParameter, which carries Direction/DbType/Size so OUTPUT and INPUT-OUTPUT values can be read back after execution via ISqlDatabaseManager.ExecuteNonQueryAsync(string procedureName, IEnumerable<OmniParameter> parameters, ...).
var parameters = new[]
{
OmniParameter.In("SOURCE_TRANS_ID", sourceTransId),
OmniParameter.In("AMOUNT_REQUESTED", amount),
OmniParameter.Out("RESULT_1SUCCESS_0FAILED", DbType.Int32),
OmniParameter.Out("RESULT_MESSAGE", DbType.String, size: -1), // -1 = MAX
OmniParameter.InOut("RUNNING_TOTAL", currentTotal, DbType.Decimal),
};
DatabaseResult result = await db.ExecuteNonQueryAsync("dbo.MOBWEB_GET_NORMAL_LOAN_APPL", parameters);
bool success = result.GetOutput<int>("RESULT_1SUCCESS_0FAILED") == 1;
string message = result.GetOutput<string>("RESULT_MESSAGE") ?? "";
DatabaseResult.OutputParameters holds the raw values keyed by parameter name (no provider prefix); GetOutput<T> converts and returns default when the parameter is absent or NULL.
Exceptions
try
{
await db.ExecuteAsync("INSERT INTO users (email) VALUES (@email)", new { email });
}
catch (DatabaseConstraintViolationException ex)
{
// Unique/FK/check/not-null violation — derives from DatabaseManagerException,
// so existing `catch (DatabaseManagerException)` sites still catch it too.
Console.WriteLine($"constraint violated: {ex.ProviderErrorCode}");
}
catch (DatabaseManagerException ex)
{
Console.WriteLine($"{ex.ErrorCode}: {ex.Message}"); // ErrorCode: Unknown | Transient | Timeout | ConstraintViolation | ConnectionFailure
Console.WriteLine(ex.InnerException); // original provider exception is always preserved
}
| Exception | Thrown by | Notable members |
|---|---|---|
DatabaseManagerException |
SQL execution failures | ErrorCode (DatabaseErrorCode), ProviderErrorCode (raw SqlState / error number) |
DatabaseConstraintViolationException |
Unique/FK/check/not-null violations | Derives from DatabaseManagerException; ErrorCode is always ConstraintViolation |
DatabaseConnectionException |
Connection establishment failures | ErrorCode (always ConnectionFailure), ProviderErrorCode |
CacheManagerException |
Cache write/delete/increment failures | Reason (CacheReason — the same enum CacheResult<T>.FailureReason uses on reads) |
QueueManagerException |
Message queue / pub-sub write-path failures | Reason (QueueReason — the same enum QueueResult<T>.FailureReason uses on reads) |
OmniConcurrencyException |
[RowVersion] mismatch in SaveAsync |
EntityType; also has generic (string) / (string, Exception) constructors |
Every exception's inner-exception constructor preserves the original provider exception (stack trace included) — nothing is swallowed into a message string.
Schema annotations
[Table("users")]
[SoftDelete("deleted_at")]
[CacheKey("user")]
[CacheExpiry(hours: 1)]
public class User
{
[PrimaryKey("id", autoGenerate: true)]
public int Id { get; set; }
[Column("name")]
public string Name { get; set; } = "";
[Column("email")]
[UniqueKey]
public string Email { get; set; } = "";
[Column("created_at")]
[NotUpdated] // excluded from UPDATE SET clauses
public DateTime CreatedAt { get; set; }
[Column("version")]
[NotInserted] // excluded from INSERT (managed by DB trigger/default)
public int Version { get; set; }
[RowVersion] // optimistic concurrency — SaveAsync increments and checks this
public long RowVersion { get; set; }
[Column("deleted_at")]
public DateTime? DeletedAt { get; set; }
[NotMapped] // never read from or written to the DB
public string Label => $"{Name} <{Email}>";
}
// [Index] — repeatable, defines DB indexes created by EnsureCreatedAsync
[Table("posts")]
[Index("idx_posts_author", "author_id")]
[Index("idx_posts_slug", "slug", unique: true)]
public class Post
{
[PrimaryKey] // no-arg form — uses the property name ("Id") as column name
public Guid Id { get; set; }
[Column(Name = "author_id")] // property-syntax alternative to [Column("author_id")]
public int AuthorId { get; set; }
[Column("slug")]
public string Slug { get; set; } = "";
}
| Attribute | Target | Purpose |
|---|---|---|
[Table("name")] |
Class | Maps to a table name; defaults to class name |
[Column("name")] or [Column(Name="name")] |
Property | Maps to a column name; defaults to property name. Nullable = true forces NULL, ForceNotNull = true forces NOT NULL in generated DDL — overrides the default type-based inference |
[PrimaryKey] / [PrimaryKey("name", autoGenerate)] |
Property | Marks the PK; autoGenerate uses SERIAL / IDENTITY / AUTO_INCREMENT. The no-arg form uses the property name as the column name |
[UniqueKey] |
Property | Emits UNIQUE in DDL |
[NotMapped] |
Property | Excluded from all SQL operations |
[NotInserted] |
Property | Excluded from INSERT statements |
[NotUpdated] |
Property | Excluded from UPDATE SET clauses |
[RowVersion] |
Property | Optimistic concurrency token (long/int). SaveAsync appends AND col = @expected to the WHERE clause and increments on success; throws OmniConcurrencyException on mismatch |
[Index("name", "col1,col2")] |
Class | Declares a non-unique (or unique) index created by EnsureCreatedAsync. Repeatable. unique: true emits a UNIQUE index. Method (e.g. "gin") selects a Postgres/Cockroach-specific index access method — ignored on SQL Server/MySQL/SQLite; Postgres doesn't support combining Method = "gin" with unique: true |
[SoftDelete("col")] |
Class | DeleteAsync sets this column; queries filter IS NULL automatically |
[HasMany(type, foreignKey)] |
Property | One-to-many eager loading relationship; eager-loaded via Include<TRelated> |
[HasOne(type, foreignKey)] |
Property | One-to-one eager loading relationship; eager-loaded via Include<TRelated> |
[BelongsTo(type, foreignKey)] |
Property | Inverse of HasMany / HasOne; eager-loaded via Include<TRelated> |
[ManyToMany(type, joinTable, sourceFk, targetFk)] |
Property | Many-to-many via a junction table; eager-loaded via IncludeMany<TRelated> (in OmniDataAccess.SqlDatabases) |
[CacheKey("prefix")] |
Class | Key prefix for OmniCache entity operations |
[CacheExpiry(h, m, s)] |
Class | Default TTL for OmniCache entity operations |
Where to look in the codebase
| Path | Contents |
|---|---|
Configs/DatabaseManagerOptions.cs |
SQL manager configuration |
Configs/CacheManagerOptions.cs |
Cache manager configuration |
Configs/MessageQueueOptions.cs |
Message queue / pub-sub configuration (extends CacheManagerOptions) |
Annotations/SchemaAttributes.cs |
All schema and lifecycle attributes |
Interfaces/IDatabaseManager.cs |
Base ping interface |
CacheResult.cs / DatabaseResult.cs / PaginationResult.cs / QueueResult.cs |
Result types |
QueueMessage.cs / PendingMessageInfo.cs |
Message queue envelope / pending-message metadata types |
OmniParameter.cs |
Execution-time stored procedure parameter (Direction/DbType/Size) |
ORM/IOmniHooks.cs |
OmniDB lifecycle callback interface (BeforeCreate/AfterCreate/etc.) |
Exceptions/ |
DatabaseManagerException, DatabaseConnectionException, DatabaseConstraintViolationException, CacheManagerException, QueueManagerException, OmniConcurrencyException |
Utils/Enums.cs |
DatabaseErrorCode, CacheReason, QueueReason, and other shared enums |
Utils/JsonHelpers.cs |
JSON detection helpers |
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net8.0
- Microsoft.Extensions.Logging (>= 8.0.1)
- Microsoft.Extensions.Logging.Console (>= 8.0.1)
- Microsoft.Extensions.Options (>= 8.0.2)
NuGet packages (3)
Showing the top 3 NuGet packages that depend on OmniDataAccess.Core:
| Package | Downloads |
|---|---|
|
OmniDataAccess.SqlDatabases
Package Description |
|
|
OmniDataAccess.NoSqlDatabases
Package Description |
|
|
OmniDataAccess
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.2.0 | 233 | 8/2/2026 |
| 1.2.0-preview.260729.1 | 145 | 7/29/2026 |
| 1.2.0-preview.260719.1 | 123 | 7/19/2026 |
| 1.2.0-preview.260715.1 | 104 | 7/15/2026 |
| 1.2.0-preview.260714.1 | 73 | 7/14/2026 |
| 1.2.0-preview.260706.1 | 112 | 7/6/2026 |
| 1.2.0-preview.260704.2 | 85 | 7/4/2026 |
| 1.2.0-preview.260703.1 | 102 | 7/3/2026 |
| 1.1.1 | 610 | 1/22/2026 |
| 1.1.0 | 701 | 10/19/2025 |
| 1.1.0-rc.1.251006 | 446 | 10/6/2025 |
| 1.0.6-rc.1.250921 | 315 | 9/21/2025 |
| 1.0.5 | 331 | 9/14/2025 |
| 1.0.4 | 296 | 8/21/2025 |
| 1.0.3 | 209 | 8/12/2025 |
| 1.0.3-rc1 | 338 | 8/13/2025 |
| 1.0.2 | 1,028 | 7/21/2025 |
| 1.0.1 | 163 | 7/18/2025 |