OmniDataAccess.Core 1.2.0

dotnet add package OmniDataAccess.Core --version 1.2.0
                    
NuGet\Install-Package OmniDataAccess.Core -Version 1.2.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="OmniDataAccess.Core" Version="1.2.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="OmniDataAccess.Core" Version="1.2.0" />
                    
Directory.Packages.props
<PackageReference Include="OmniDataAccess.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add OmniDataAccess.Core --version 1.2.0
                    
#r "nuget: OmniDataAccess.Core, 1.2.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package OmniDataAccess.Core@1.2.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=OmniDataAccess.Core&version=1.2.0
                    
Install as a Cake Addin
#tool nuget:?package=OmniDataAccess.Core&version=1.2.0
                    
Install as a Cake Tool

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 by GetPendingAsync)
  • Procedure metadata: Procedure, ProcedureParameter (DDL — used by CreateProcedureAsync/CreateFunctionAsync), OmniParameter (execution — binds stored procedure calls, including OUTPUT/INPUT-OUTPUT parameters)
  • Exceptions: DatabaseManagerException, DatabaseConnectionException, DatabaseConstraintViolationException, CacheManagerException, QueueManagerException, OmniConcurrencyException
  • Configuration: DatabaseManagerOptions, CacheManagerOptions, MessageQueueOptions (extends CacheManagerOptions)
  • 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/AfterDelete lifecycle callbacks, called automatically by OmniDB when 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 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
Loading failed