TCIS.Pluggable.Persistence.Oracle
1.0.0-rc.19
dotnet add package TCIS.Pluggable.Persistence.Oracle --version 1.0.0-rc.19
NuGet\Install-Package TCIS.Pluggable.Persistence.Oracle -Version 1.0.0-rc.19
<PackageReference Include="TCIS.Pluggable.Persistence.Oracle" Version="1.0.0-rc.19" />
<PackageVersion Include="TCIS.Pluggable.Persistence.Oracle" Version="1.0.0-rc.19" />
<PackageReference Include="TCIS.Pluggable.Persistence.Oracle" />
paket add TCIS.Pluggable.Persistence.Oracle --version 1.0.0-rc.19
#r "nuget: TCIS.Pluggable.Persistence.Oracle, 1.0.0-rc.19"
#:package TCIS.Pluggable.Persistence.Oracle@1.0.0-rc.19
#addin nuget:?package=TCIS.Pluggable.Persistence.Oracle&version=1.0.0-rc.19&prerelease
#tool nuget:?package=TCIS.Pluggable.Persistence.Oracle&version=1.0.0-rc.19&prerelease
TCIS.Pluggable.Persistence.Oracle
Oracle provider for the Pluggable multi-tenant data layer. Supports all three tiers — Virtual Private Database, schema per tenant, and database per tenant.
Shared behaviour — model composition, query filters, audit stamping — lives in
TCIS.Pluggable.Persistence.EntityFrameworkCore.
1. Registration
dotnet add package TCIS.Pluggable.Persistence.Oracle
builder.Services.AddPluggableOracle<TosDbContext>(commandTimeoutSeconds: 30);
Do not pass a connection string. It is resolved per request from the Tenant Store through
IMultiTenantContextAccessor<TenantInfo>.
2. Tier support
| Tier | Mechanism | Identifier used |
|---|---|---|
| Tier 1 — Row level (VPD) | DBMS_SESSION.SET_CONTEXT('TCIS_CTX', 'TENANT_ID', …) |
TenantInfo.Id (GUID) |
| Tier 2 — Schema per tenant | ALTER SESSION SET CURRENT_SCHEMA |
TenantInfo.Identifier (site code) |
| Tier 3 — Database per tenant | no-op initializer | — |
Tier 2 takes the schema name from
TenantInfo.Identifier, notTenantInfo.Id. The identifier becomes an Oracle schema name and must pass the identifier whitelist; a GUID contains-and is always rejected.
In Oracle a schema is a user, so Tier 2 means one database user per tenant. Grant the application account the privileges to switch into each of them, and nothing more.
3. Tier 1 — application context and VPD
OracleRlsConnectionInitializer sets an application context on Open() and clears it on Close(). Your VPD policy function reads it back:
CREATE OR REPLACE FUNCTION sec.tenant_predicate(
schema_name IN VARCHAR2, table_name IN VARCHAR2) RETURN VARCHAR2 AS
BEGIN
RETURN 'TENANT_ID = SYS_CONTEXT(''TCIS_CTX'', ''TENANT_ID'')';
END;
The context namespace TCIS_CTX must be created with a trusted package so that only that package can set it — otherwise any session could set its own tenant id and defeat the policy:
CREATE CONTEXT TCIS_CTX USING sec.tenant_ctx_pkg;
A blank tenant id runs the cleanup command, clearing any context left over from a pooled session. The predicate then matches no row: fail-closed.
4. Tier status
Tier 3 is the simplest design here (a no-op initializer) but has no automated test coverage yet, and tenant resolution is its single point of failure — if the wrong connection string is resolved, nothing downstream will catch it. Ironically it is also the tier most likely to be chosen by a large port.
Treat a Tier 3 rollout as needing its own isolation test before go-live.
5. Pitfalls
| # | Pitfall | Consequence |
|---|---|---|
| 1 | Using a GUID as the Tier 2 identifier | Whitelist rejection — use the site code |
| 2 | Creating TCIS_CTX without a trusted package |
Any session can set its own tenant id and bypass VPD |
| 3 | Granting the application account EXEMPT ACCESS POLICY |
VPD no longer applies to it — the defence is gone |
| 4 | Assuming the EF query filter protects Dapper queries | It does not; on Tier 1 only VPD stands in the way |
| 5 | Relying on commandTimeoutSeconds for Dapper |
It applies to EF Core only |
| 6 | Deploying Tier 3 without an isolation test | Tenant resolution is the only thing preventing a cross-tenant connection |
6. A note on terminology
FORCE ROW LEVEL SECURITY and BYPASSRLS are PostgreSQL concepts and have no Oracle equivalent. The Oracle counterparts are VPD policies plus the EXEMPT ACCESS POLICY privilege — do not port a PostgreSQL checklist verbatim.
| 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
- Dapper (>= 2.1.66)
- Microsoft.EntityFrameworkCore (>= 8.0.13)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.13)
- Microsoft.Extensions.Caching.Abstractions (>= 8.0.0)
- Microsoft.Extensions.Caching.Memory (>= 8.0.1)
- Microsoft.Extensions.Configuration (>= 9.0.0)
- Microsoft.Extensions.Configuration.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Configuration.Binder (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection (>= 9.0.0)
- Microsoft.Extensions.DependencyInjection.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Http (>= 9.0.0)
- Microsoft.Extensions.Logging (>= 9.0.0)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.0)
- Microsoft.Extensions.Options (>= 9.0.0)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 9.0.0)
- Microsoft.Extensions.Options.DataAnnotations (>= 8.0.0)
- Oracle.EntityFrameworkCore (>= 8.23.60)
- TCIS.Core (>= 1.0.0-rc.19)
- TCIS.MultiTenancy (>= 1.0.0-rc.19)
- TCIS.Pluggable.Persistence.EntityFrameworkCore (>= 1.0.0-rc.19)
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 |
|---|---|---|
| 1.0.0-rc.19 | 10 | 8/13/2026 |
| 1.0.0-rc.18 | 6 | 8/13/2026 |
| 1.0.0-rc.17 | 18 | 8/13/2026 |
| 1.0.0-rc.16 | 32 | 8/13/2026 |
| 1.0.0-rc.15 | 38 | 8/12/2026 |
| 1.0.0-rc.14 | 46 | 8/12/2026 |
| 1.0.0-rc.13 | 40 | 8/11/2026 |
| 1.0.0-rc.12 | 47 | 8/10/2026 |
| 1.0.0-rc.11 | 61 | 7/28/2026 |
| 1.0.0-rc.10 | 54 | 7/24/2026 |
| 1.0.0-rc.9 | 51 | 7/21/2026 |
| 1.0.0-rc.8 | 51 | 7/21/2026 |