Entity Framework Core'da Global Query Filters ile Multi-tenant Mimari Tasarımı
Modern SaaS uygulamalarında en yaygın mimari modellerden biri, tüm müşterilerin (tenant) verilerini aynı veritabanında ancak izole edilmiş şekilde tutmaktır. Bu yapıda en büyük risk, bir geliştiricinin sorgu yazarken "TenantId" filtresini unutması ve verilerin birbirine sızmasıdır. Global Query Filters, bu riski ortadan kaldıran merkezi bir güvenlik ağı sunar.
1. Tenant Kimliğini Belirleme (Interface Yapısı)
İlk adım, tenant bazlı olan tüm entity'lerimizi işaretleyecek bir arayüz oluşturmaktır. Bu sayede merkezi konfigürasyonda hangi tablolara filtre uygulanacağını otomatik olarak belirleyebiliriz.
public interface ITenantEntity
{
Guid TenantId { get; set; }
}
public class Product : ITenantEntity
{
public int Id { get; set; }
public string Name { get; set; }
public Guid TenantId { get; set; }
}
2. Tenant Service ve Middleware
Uygulamaya gelen her isteğin hangi tenant'a ait olduğunu (header, domain veya claim üzerinden) belirleyen bir servis tasarlamalıyız. Bu servis, DbContext içinde kullanılacaktır.
public interface ITenantService
{
Guid GetTenantId();
}
3. DbContext Üzerinde Global Filtre Yapılandırması
OnModelCreating içinde, ITenantEntity arayüzünü uygulayan tüm sınıflara otomatik olarak filtre ekliyoruz. Bu filtre, veritabanına giden her sorgunun sonuna otomatik olarak bir WHERE koşulu ekler.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
if (typeof(ITenantEntity).IsAssignableFrom(entityType.ClrType))
{
modelBuilder.Entity(entityType.ClrType).HasQueryFilter(ConvertFilterExpression(entityType.ClrType));
}
}
}
4. Filtreyi Devre Dışı Bırakma (IgnoreQueryFilters)
Bazı durumlarda (örneğin bir admin panelinde tüm verileri görmek istediğinizde), bu global filtreyi devre dışı bırakmanız gerekebilir. Bunun için IgnoreQueryFilters() metodunu kullanabilirsiniz:
var allProducts = await _context.Products
.IgnoreQueryFilters()
.ToListAsync();
Sonuç
Global Query Filters kullanarak hata payını minimize eder, kodunuzu daha temiz ve güvenli hale getirirsiniz. Ancak unutmayın; bu filtreler FromSqlRaw gibi ham SQL sorgularında otomatik olarak uygulanmaz, bu yüzden ham SQL kullanırken dikkatli olunmalıdır.