Levge.Tenancy
2.3.0
dotnet add package Levge.Tenancy --version 2.3.0
NuGet\Install-Package Levge.Tenancy -Version 2.3.0
<PackageReference Include="Levge.Tenancy" Version="2.3.0" />
<PackageVersion Include="Levge.Tenancy" Version="2.3.0" />
<PackageReference Include="Levge.Tenancy" />
paket add Levge.Tenancy --version 2.3.0
#r "nuget: Levge.Tenancy, 2.3.0"
#:package Levge.Tenancy@2.3.0
#addin nuget:?package=Levge.Tenancy&version=2.3.0
#tool nuget:?package=Levge.Tenancy&version=2.3.0
Levge.Tenancy
.NET 10 SaaS uygulamaları için çok kiracılı (multi-tenant) altyapı paketi.
JWT claim tabanlı tenant çözümleme, EF Core Global Query Filter ve tenant yaşam döngüsü yönetimi.
İçindekiler
- Kurulum
- Hızlı Başlangıç
- TenantBase — Kendi Tenant Entity'ni Oluştur
- DbContext Entegrasyonu
- ITenantContext
- ITenantService
- Global Query Filter
- TenantStatus
- Bağımlılıklar
Kurulum
dotnet add package Levge.Tenancy
dotnet add package Levge.Identity
Hızlı Başlangıç
// Program.cs
builder.Services
.AddLevgeIdentity(jwtConfig)
.AddLevgeTenancy<AppDbContext, Tenant>();
app.UseAuthentication();
app.UseAuthorization();
TenantBase — Kendi Tenant Entity'ni Oluştur
TenantBase'den türet, ihtiyacına göre alan ekle:
public class Tenant : TenantBase
{
public string? LogoUrl { get; set; }
public string? WebsiteUrl { get; set; }
// İleride: public long? PlanId { get; set; } ← Levge.Subscription için
}
TenantBase şu alanları yerleşik olarak içerir:
| Alan | Tür | Açıklama |
|---|---|---|
Name |
string |
Görünen ad |
Slug |
string |
URL dostu benzersiz tanımlayıcı |
ContactEmail |
string? |
İletişim e-postası |
Phone |
string? |
Telefon numarası |
Status |
TenantStatus |
Yaşam döngüsü durumu |
TrialEndsAt |
DateTime? |
Deneme bitiş tarihi |
Notes |
string? |
Notlar |
IsActive |
bool |
Aktif/pasif (FullAuditableEntity'den) |
CreatedAt |
DateTime |
Oluşturma zamanı |
UpdatedAt |
DateTime? |
Güncelleme zamanı |
IsDeleted |
bool |
Yumuşak silme |
DbContext Entegrasyonu
Seçenek A — LevgeTenantDbContext'ten türet
public class AppDbContext : LevgeTenantDbContext<Tenant>
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
public DbSet<Order> Orders { get; set; } = null!;
}
Seçenek B — Mevcut hiyerarşiye ekle (IdentityDbContext, LevgeAuditDbContext vb.)
public class AppDbContext : LevgeAuditDbContext, ITenantDbContext<Tenant>
{
public DbSet<Tenant> Tenants { get; set; } = null!;
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureLevgeTenancy<Tenant>();
}
}
Global Query Filter ile birlikte
public class AppDbContext : LevgeTenantDbContext<Tenant>
{
private readonly ITenantContext _tenantContext;
public AppDbContext(DbContextOptions<AppDbContext> options, ITenantContext tenantContext)
: base(options)
{
_tenantContext = tenantContext;
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
if (_tenantContext.HasTenant)
modelBuilder.AddTenantQueryFilters(_tenantContext);
}
}
ITenantContext
JWT claim'lerinden otomatik çözümlenen kiracı bağlamı:
public class OrderService
{
private readonly ITenantContext _tenantContext;
public OrderService(ITenantContext tenantContext)
=> _tenantContext = tenantContext;
public void Create()
{
long tenantId = _tenantContext.RequiredTenantId; // yoksa LevgeTenantException fırlatır
bool hasTenant = _tenantContext.HasTenant;
string? name = _tenantContext.TenantName;
}
}
| Üye | Tür | Açıklama |
|---|---|---|
TenantId |
long? |
JWT'den okunan tenant ID |
TenantName |
string? |
JWT'den okunan tenant adı |
HasTenant |
bool |
Geçerli tenant bağlamı var mı |
RequiredTenantId |
long |
Zorunlu erişim; yoksa exception fırlatır |
ITenantService
public interface ITenantService<TTenant>
{
Task<TTenant?> GetByIdAsync(long id, CancellationToken ct = default);
Task<TTenant?> GetBySlugAsync(string slug, CancellationToken ct = default);
Task<List<TTenant>> GetAllAsync(CancellationToken ct = default);
Task<List<TTenant>> GetByStatusAsync(TenantStatus status, CancellationToken ct = default);
Task<bool> SlugExistsAsync(string slug, long? excludeId = null, CancellationToken ct = default);
Task<bool> IsActiveAsync(long tenantId, CancellationToken ct = default);
Task<Result> UpdateStatusAsync(long tenantId, TenantStatus status, CancellationToken ct = default);
}
// Kullanım
var tenant = await _tenantService.GetBySlugAsync("acme-corp");
bool active = await _tenantService.IsActiveAsync(tenantId);
await _tenantService.UpdateStatusAsync(tenantId, TenantStatus.Suspended);
Global Query Filter
ITenantEntity uygulayan tüm entity'lere otomatik WHERE TenantId = @currentTenantId filtresi eklenir.
Levge.Domain'deki FullAuditableTenantEntity veya TenantEntity'den türeyen entity'ler otomatik kapsama girer.
// Filtre devredışı bırakmak için (SuperAdmin senaryoları)
_dbContext.Orders.IgnoreQueryFilters().ToListAsync();
TenantStatus
| Değer | Açıklama |
|---|---|
Active |
Normal çalışıyor |
Trial |
Deneme sürecinde |
Suspended |
Askıya alınmış |
Cancelled |
Abonelik iptal |
Demo |
Demo / test kiracısı |
Bağımlılıklar
| Paket | Amaç |
|---|---|
Microsoft.AspNetCore.App |
ASP.NET Core altyapısı |
Microsoft.EntityFrameworkCore |
EF Core ORM |
Microsoft.EntityFrameworkCore.Relational |
Index ve model yapılandırma |
Levge.Identity |
ICurrentUser üzerinden JWT claim erişimi |
Levge.Domain |
TenantBase'in türediği entity hiyerarşisi |
Levge.Exceptions |
LevgeTenantException |
| 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
- Levge.Identity (>= 2.3.0)
- Microsoft.EntityFrameworkCore (>= 10.0.7)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.