Swevo.EFCore.MultiTenant
1.0.1
Prefix Reserved
dotnet add package Swevo.EFCore.MultiTenant --version 1.0.1
NuGet\Install-Package Swevo.EFCore.MultiTenant -Version 1.0.1
<PackageReference Include="Swevo.EFCore.MultiTenant" Version="1.0.1" />
<PackageVersion Include="Swevo.EFCore.MultiTenant" Version="1.0.1" />
<PackageReference Include="Swevo.EFCore.MultiTenant" />
paket add Swevo.EFCore.MultiTenant --version 1.0.1
#r "nuget: Swevo.EFCore.MultiTenant, 1.0.1"
#:package Swevo.EFCore.MultiTenant@1.0.1
#addin nuget:?package=Swevo.EFCore.MultiTenant&version=1.0.1
#tool nuget:?package=Swevo.EFCore.MultiTenant&version=1.0.1
Swevo.EFCore.MultiTenant
Compile-time multi-tenancy for EF Core. Stamp a [Tenant] attribute on any entity and the source generator wires up TenantId, a save interceptor, and global query filters automatically.
Quick-start
dotnet add package Swevo.EFCore.MultiTenant
1 — Mark your entities
using EFCore.MultiTenant;
[Tenant]
public partial class Order
{
public int Id { get; set; }
public string Description { get; set; } = "";
// TenantId { get; set; } is generated automatically
}
The class must be
partial. Non-partial classes produce diagnosticMTNT001.
2 — Implement ITenantContext
public class HttpTenantContext(IHttpContextAccessor http) : ITenantContext
{
public string TenantId =>
http.HttpContext?.Request.Headers["X-Tenant-Id"].FirstOrDefault() ?? "";
}
Register it as scoped in your DI container:
builder.Services.AddScoped<ITenantContext, HttpTenantContext>();
3 — Configure DbContext
public class AppDbContext(DbContextOptions<AppDbContext> options, ITenantContext tenant)
: DbContext(options)
{
public DbSet<Order> Orders => Set<Order>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
=> modelBuilder.AddTenantQueryFilters(tenant);
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.AddTenantInterceptor(tenant);
}
That's it. Every SaveChanges / SaveChangesAsync call stamps TenantId on new entities, and every query automatically filters by the current tenant.
How it works
| Piece | What it does |
|---|---|
[Tenant] attribute |
Marks the entity for code generation |
| Source generator | Emits TenantId property + ITenantEntity implementation |
TenantInterceptor |
ISaveChangesInterceptor — stamps TenantId on Added entries |
AddTenantQueryFilters |
Adds a global WHERE TenantId = @current filter to every tenant entity |
Bypass the filter
Use IgnoreQueryFilters() for admin/reporting queries:
var allOrders = await db.Orders.IgnoreQueryFilters().ToListAsync();
Stacking with other Swevo packages
[Tenant] // Swevo.EFCore.MultiTenant — adds TenantId
[Auditable] // Swevo.AutoAudit — adds CreatedAt / UpdatedAt
[SoftDelete] // Swevo.EFCore.SoftDelete — adds IsDeleted
public partial class Order { ... }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.AddTenantInterceptor(tenant)
.AddAuditInterceptor(clock)
.AddSoftDeleteInterceptor();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddTenantQueryFilters(tenant);
modelBuilder.AddSoftDeleteQueryFilters();
}
Requirements
- .NET 8+
- EF Core 8+
License
MIT
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
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.1 | 137 | 6/26/2026 |
1.0.0: [Tenant] generates TenantId + ITenantEntity. TenantInterceptor stamps new rows. AddTenantQueryFilters() isolates rows per tenant. MTNT001 for non-partial classes.