Omniport 1.0.0
dotnet add package Omniport --version 1.0.0
NuGet\Install-Package Omniport -Version 1.0.0
<PackageReference Include="Omniport" Version="1.0.0" />
<PackageVersion Include="Omniport" Version="1.0.0" />
<PackageReference Include="Omniport" />
paket add Omniport --version 1.0.0
#r "nuget: Omniport, 1.0.0"
#:package Omniport@1.0.0
#addin nuget:?package=Omniport&version=1.0.0
#tool nuget:?package=Omniport&version=1.0.0
<p align="center"> <img src="omniport_logo.svg" alt="Omniport logo" width="180" /> </p>
<h1 align="center">Omniport</h1>
<p align="center"> A Standardized Provider Abstraction Library (SPAL) for swapping SQL Server, PostgreSQL, Cosmos DB, and MongoDB storage backends via configuration only. </p>
What is Omniport?
Omniport gives every microservice a single shared contract,
IStorageBrokerProvider, that each database provider implements. A
microservice keeps its own StorageBroker — it still owns its entity model,
OnModelCreating, and migrations — but delegates all provider-specific
configuration (which EF Core provider to use, connection strings, dialect
quirks) to whichever IStorageBrokerProvider is injected.
The result: swapping a microservice's database backend is a config value
change (Storage:Backend) plus a connection string — no recompilation of
business logic.
This follows The Standard, Chapter 1.8 — Standardized Provider Abstraction Libraries (SPAL).
Packages
| Package | Purpose |
|---|---|
Omniport |
The shared contract (IStorageBrokerProvider, TargetServerType). Every other package depends on it. Kept small and stable — a breaking change here is a breaking change everywhere. |
Omniport.SqlServer |
SQL Server provider (Microsoft.EntityFrameworkCore.SqlServer). |
Omniport.PostgreSql |
PostgreSQL provider (Npgsql.EntityFrameworkCore.PostgreSQL), plus a DateTimeOffsetTruncationInterceptor that handles the Postgres timestamptz precision mismatch against .NET's DateTimeOffset. |
Omniport.Cosmos |
Cosmos DB provider (Microsoft.EntityFrameworkCore.Cosmos), with local-emulator support via CosmosStorageBrokerOptions. |
Omniport.MongoDb |
MongoDB provider (MongoDB.EntityFrameworkCore), with local-instance support via MongoDbStorageBrokerOptions. |
Only reference the providers a given microservice actually needs — there's no requirement to pull in all four if a service will only ever run against one or two backends.
Install
dotnet add package Omniport
dotnet add package Omniport.SqlServer # or PostgreSql / Cosmos / MongoDb
Pin exact versions in consuming services — don't float:
<PackageReference Include="Omniport" Version="1.0.0" />
<PackageReference Include="Omniport.SqlServer" Version="1.0.0" />
Usage
1. StorageBroker — delegate provider config to Omniport
public partial class StorageBroker : EFxceptionsContext, IStorageBroker
{
private readonly IStorageBrokerProvider storageBrokerProvider;
public StorageBroker(IStorageBrokerProvider storageBrokerProvider)
{
this.storageBrokerProvider = storageBrokerProvider;
// Cosmos and MongoDB are schemaless — no relational migration history.
if (storageBrokerProvider is CosmosStorageBrokerProvider
|| storageBrokerProvider is MongoDbStorageBrokerProvider)
{
this.Database.EnsureCreated();
}
else
{
this.Database.Migrate();
}
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) =>
this.storageBrokerProvider.Configure(optionsBuilder);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// this service's own entity configuration goes here first
this.storageBrokerProvider.ConfigureModel(modelBuilder);
}
protected override void ConfigureConventions(
ModelConfigurationBuilder configurationBuilder) =>
this.storageBrokerProvider.ConfigureConventions(configurationBuilder);
}
2. Program.cs — pick a provider from config
string backend = builder.Configuration["Storage:Backend"]; // "SqlServer" | "Postgres" | "Cosmos" | "MongoDb"
string connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
string migrationsAssembly = $"YourService.{backend}";
builder.Services.AddSingleton<IStorageBrokerProvider>(_ => backend switch
{
"SqlServer" => new SqlServerStorageBrokerProvider(connectionString, migrationsAssembly),
"Postgres" => new PostgreSqlStorageBrokerProvider(connectionString, migrationsAssembly),
"Cosmos" => new CosmosStorageBrokerProvider(new CosmosStorageBrokerOptions
{
ConnectionString = connectionString,
DatabaseName = builder.Configuration["Storage:Cosmos:DatabaseName"],
TargetServerType = builder.Configuration.GetValue<bool>("Storage:UseLocalEmulator")
? TargetServerType.Local
: TargetServerType.Remote
}),
"MongoDb" => new MongoDbStorageBrokerProvider(new MongoDbStorageBrokerOptions
{
ConnectionString = connectionString,
DatabaseName = builder.Configuration["Storage:MongoDb:DatabaseName"],
TargetServerType = builder.Configuration.GetValue<bool>("Storage:UseLocalEmulator")
? TargetServerType.Local
: TargetServerType.Remote
}),
_ => throw new NotSupportedException($"Unsupported storage backend: {backend}")
});
builder.Services.AddDbContext<StorageBroker>();
3. appsettings.json
{
"Storage": {
"Backend": "SqlServer",
"UseLocalEmulator": false,
"Cosmos": { "DatabaseName": "YourServiceDB" },
"MongoDb": { "DatabaseName": "YourServiceDB" }
},
"ConnectionStrings": {
"DefaultConnection": "Server=...;Database=...;"
}
}
Switching backends is now: change Storage:Backend + ConnectionStrings:DefaultConnection.
Nothing else in the microservice changes.
4. Migrations (SQL Server / PostgreSQL only)
Cosmos and MongoDB are schemaless — they don't support dotnet ef migrations.
Provisioning happens via Database.EnsureCreated() at startup instead (see
the StorageBroker snippet above).
For SQL Server and PostgreSQL, each relational provider project in the
consuming microservice's own repo needs a design-time factory so
dotnet ef can construct a StorageBroker without full app startup:
internal class SqlServerContextFactory : IDesignTimeDbContextFactory<StorageBroker>
{
public StorageBroker CreateDbContext(string[] args)
{
string connectionString =
Environment.GetEnvironmentVariable("SQLSERVER_CONNECTION_STRING")
?? "Server=localhost;Database=YourServiceDB;Trusted_Connection=True;TrustServerCertificate=True";
return new StorageBroker(
new SqlServerStorageBrokerProvider(connectionString, "YourService.SqlServer"));
}
}
dotnet ef migrations add InitialCreate --project YourService.SqlServer --context StorageBroker --output-dir Migrations
dotnet ef database update --project YourService.SqlServer --context StorageBroker
Give the same migration the same name across providers (InitialCreate,
AddUsageLimitIndex, ...) even though they live in separate folders, so it's
obvious they correspond to the same logical schema change. Run
dotnet ef database update for every provider on every deploy, not just the
currently-active one, so a future Storage:Backend flip doesn't hit a
stale/uninitialized database.
5. Provider-specific notes
PostgreSQL — ConfigureConventions maps DateTimeOffset to
timestamptz at microsecond precision, and DateTimeOffsetTruncationInterceptor
truncates outgoing DateTimeOffset parameters to match, since Postgres
timestamptz doesn't carry the full precision .NET's DateTimeOffset does.
Cosmos DB — entities need a partition key configured per-entity in the
microservice's OnModelCreating, since only the microservice knows its
entity shapes: modelBuilder.Entity<T>().HasPartitionKey(x => x.SomeProperty).
MongoDB — MongoDB.EntityFrameworkCore is newer and less
feature-complete than the relational/Cosmos EF Core providers (no migrations,
limited LINQ operator support, different owned-entity mapping). Confirm
current capabilities against the
official docs
before relying on advanced query patterns. If it's too limited for a given
service, that service can bypass DbContext and use MongoDB.Driver
directly for the affected operations while still using
MongoDbStorageBrokerProvider elsewhere — that's a microservice-level
decision and doesn't change this library.
Additional MongoDB specifics to configure in the microservice's
OnModelCreating:
// MongoDB has no native DateTimeOffset — store as UTC DateTime and convert.
modelBuilder.Entity<YourEntity>()
.Property(e => e.CreatedAt)
.HasConversion(v => v.UtcDateTime, v => new DateTimeOffset(v, TimeSpan.Zero));
// MongoDB documents use `_id` as the primary key field by convention.
modelBuilder.Entity<YourEntity>()
.Property(e => e.Id)
.HasElementName("_id");
6. External Mockability (Cloud-Foreign compliance)
For Acceptance Testing / Airplane-Mode runs, each provider supports a local
target via TargetServerType.Local:
- SQL Server / PostgreSQL — point the connection string at a Testcontainers-managed container.
- Cosmos DB — run the
Azure Cosmos DB Emulator
and set
TargetServerType.Local, which routes toCosmosStorageBrokerOptions.LocalEmulatorEndpoint/LocalEmulatorKey. - MongoDB — run the official
mongoDocker image and setTargetServerType.Local, which routes toMongoDbStorageBrokerOptions.LocalConnectionString(mongodb://localhost:27017by default).
A consuming service's acceptance test suite can drive provider selection
from environment variables (a PROVIDER / CONNECTION_STRING pair read into
a ClientBroker) so a CI matrix runs the whole suite once per backend
without any code duplication — see the pattern description in this repo's
build spec for the full example.
Versioning
Semver, strictly enforced:
- PATCH (
1.0.x) — bug fixes only, no interface changes. - MINOR (
1.x.0) — new capability, fully backward compatible (e.g. an optional overload). - MAJOR (
x.0.0) — any change toIStorageBrokerProvider's signature, or any change to a provider constructor's parameters. Every consuming microservice must bump to this deliberately after testing — never auto-float major versions.
Contributing
This repo follows The Standard.
See .agents/skills/the-standard-* for the coding, testing, and
contribution-practice rules enforced here.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Microsoft.EntityFrameworkCore (>= 10.0.10)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Omniport:
| Package | Downloads |
|---|---|
|
Omniport.PostgreSql
PostgreSQL storage broker provider for Omniport. |
|
|
Omniport.SqlServer
SQL Server storage broker provider for Omniport. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.0 | 105 | 8/11/2026 |