🏢 معماری چند-مستأجره با EF Core (قسمت ۲):
هر مستأجر، دیتابیس خودش
در قسمت اول، روش ایزولهسازی منطقی (یک دیتابیس برای همه) رو با Query Filters پیادهسازی کردیم. این روش برای خیلی از پروژهها عالیه.
اما گاهی اوقات به ایزولهسازی فیزیکی نیاز داریم؛ یعنی هر مشتری، دیتابیس کاملاً مجزای خودش رو داشته باشه تا دادهها به صورت فیزیکی از هم جدا باشن. امروز با این روش پیشرفته و امن آشنا میشیم.
1️⃣ چالش جدید: مدیریت Connection String داینامیک 🔌
در این سناریو، دیگه Query Filters به کارمون نمیاد، چون با دیتابیسهای مختلفی سر و کار داریم. چالش اصلی ما اینه که به ازای هر درخواست، بتونیم DbContext رو با Connection String مخصوص همون مستأجر پیکربندی کنیم.
2️⃣ پیادهسازی قدم به قدم
قدم اول: ذخیره اطلاعات مستأجرها ⚙️
اول از همه، باید اطلاعات هر مستأجر و Connection String دیتابیسش رو یه جا ذخیره کنیم. برای مثال، در فایل appsettings.json:
"Tenants": [
{ "Id": "tenant-1", "ConnectionString": "Host=tenant1.db;Database=db1" },
{ "Id": "tenant-2", "ConnectionString": "Host=tenant2.db;Database=db2" }
]
قدم دوم: آپدیت کردن TenantProvider 🕵️♂️حالا TenantProvider رو آپدیت میکنیم تا علاوه بر TenantId، بتونه Connection String مربوط به مستأجر فعلی رو هم از تنظیمات بخونه و به ما بده.
public sealed class TenantProvider
{
// ... (Properties for HttpContextAccessor and TenantSettings)
public TenantProvider(
IHttpContextAccessor httpContextAccessor,
IOptions<TenantSettings> tenantsOptions)
{
// ...
_tenantSettings = tenantsOptions.Value;
}
public string TenantId => /* ... gets tenantId from header ... */;
public string GetConnectionString()
{
return _tenantSettings.Tenants
.Single(t => t.Id == TenantId).ConnectionString;
}
}
قدم سوم: جادوی DI (ثبت داینامیک DbContext) ✨این مهمترین و جادوییترین بخش کاره! ما DbContext رو جوری در Program.cs ثبت میکنیم که به ازای هر درخواست، اول TenantProvider رو اجرا کنه، Connection String رو بگیره و بعد DbContext رو با اون پیکربندی کنه.
builder.Services.AddDbContext<OrdersDbContext>((serviceProvider, options) =>
{
// TenantProvider رو از DI میگیریم
var tenantProvider = serviceProvider.GetRequiredService<TenantProvider>();
// Connection String مخصوص مستأجر فعلی رو میگیریم
var connectionString = tenantProvider.GetConnectionString();
// و DbContext رو با اون کانفیگ میکنیم
options.UseSqlServer(connectionString);
});
🔐 نکته امنیتی مهم
قرار دادن Connection Stringها به صورت مستقیم در appsettings.json برای محیط پروداکشن امن نیست. همیشه از ابزارهای مدیریت secret مثل Azure Key Vault یا NET User Secrets. برای محیط توسعه استفاده کنید.
🤔 حرف حساب و تجربه شمابا این دو روش
شما الان جعبه ابزار کاملی برای پیادهسازی هر نوع معماری چند-مستأجره در ASP.NET Core دارید.
شما تو پروژههاتون با کدوم مدل چند-مستأجری کار کردید؟ تک دیتابیس یا چند دیتابیس؟ چالشها و مزایای هر کدوم از نظر شما چیه؟
🔖 هشتگها:
#CSharp #ASPNETCore #DotNet #MultiTenancy #EntityFrameworkCore #SoftwareArchitecture #Backend