Winglet.Tenancy.EntityFrameworkCore 0.1.0

dotnet add package Winglet.Tenancy.EntityFrameworkCore --version 0.1.0
                    
NuGet\Install-Package Winglet.Tenancy.EntityFrameworkCore -Version 0.1.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="Winglet.Tenancy.EntityFrameworkCore" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Winglet.Tenancy.EntityFrameworkCore" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Winglet.Tenancy.EntityFrameworkCore" />
                    
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 Winglet.Tenancy.EntityFrameworkCore --version 0.1.0
                    
#r "nuget: Winglet.Tenancy.EntityFrameworkCore, 0.1.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 Winglet.Tenancy.EntityFrameworkCore@0.1.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=Winglet.Tenancy.EntityFrameworkCore&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Winglet.Tenancy.EntityFrameworkCore&version=0.1.0
                    
Install as a Cake Tool

Winglet.Tenancy.EntityFrameworkCore

Winglet.Tenancy.EntityFrameworkCore applies the ADR-019 SharedDatabase persistence invariants to a normal consumer-owned EF Core DbContext.

Registration

Register the core package, this EF integration, and the consumer context through normal dependency injection:

builder.Services.AddWingletTenancy(
    builder.Configuration,
    TenancyCapability.SharedDatabaseOrNone);

builder.Services.AddWingletTenancyEntityFrameworkCore();

builder.Services.AddDbContext<AppDbContext>(options =>
    options
        .UseMySql(connectionString, serverVersion)
        .UseWingletTenancy());

The context remains application-owned. It receives a per-context TenantDbContextState, implements ITenantDbContext, and applies model integration once after its own entity mappings:

public sealed class AppDbContext(
    DbContextOptions<AppDbContext> options,
    TenantDbContextState tenantState)
    : DbContext(options), ITenantDbContext
{
    public TenantDbContextState TenantState { get; } = tenantState;

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.UseWingletTenancy(this);
    }
}

Tenant-owned entities implement the marker contract:

public sealed class Document : ITenantOwned
{
    public long Id { get; set; }

    public TenantId? TenantId { get; set; }
}

The model integration discovers all ITenantOwned entity roots, maps TenantId to the canonical tenant_id Int64 column, preserves compatible explicit mapping, and combines tenant isolation with any existing query filter.

Runtime behavior

In SharedDatabase mode, normal queries require trusted tenant context and are filtered to that tenant. Added entities receive the current trusted TenantId. Tracked updates and deletes require trusted materialized state, matching ownership, and an unchanged TenantId. Detached or fabricated update/delete state fails closed.

A tenant-sensitive DbContext pins its first successfully resolved mode and TenantId for the lifetime of that context. Later tenant-sensitive use must have the same tenant context; changing or removing it fails safely. Repeated scopes for the same tenant are valid, while work for another tenant requires a new DbContext instance.

In None mode, the explicit mode is pinned without a tenant identity, tenant filtering and write enforcement are disabled, and no tenant is fabricated or assigned.

Explicitly authorized infrastructure can create a bounded read-only bypass:

using var bypass = dbContext.BeginTenantQueryFilterBypass();

The caller remains responsible for authorization and audit. Bypass state is per DbContext, nested scopes restore deterministically, and cross-tenant tracked entries are detached when the outer scope ends. The SaveChanges write guard remains active inside the bypass.

Security boundaries

  • IgnoreQueryFilters is blocked for tenant-owned entity queries and for global-root queries that explicitly or automatically include/traverse a mapped navigation to a tenant-owned entity. IgnoreAutoIncludes can keep a genuinely navigation-free global query unaffected; controlled tenant-filter bypass remains the supported cross-tenant read path.
  • ExecuteUpdate and ExecuteDelete are blocked for tenant-owned entities because they bypass tracked SaveChanges validation and could mutate TenantId.
  • Arbitrary raw SQL is not parsed or rewritten. Consumers using Database.ExecuteSqlRaw, ADO.NET, or equivalent paths against tenant-owned tables own the tenant predicate and security review.
  • AddDbContextPool and pooled factories are not supported. A pooled context reuses context-local state across DI scopes; use ordinary AddDbContext unless a future reviewed integration explicitly resets trusted tenant state.
  • The package does not implement authorization, repositories, Unit of Work wrappers, migrations, tenant registries, secret resolution, or DatabasePerTenant routing.
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
0.1.0 112 8/29/2026