Voglio creare un'applicazione web ASP.NET Core con EF Core per più clienti su un server centrale. Ogni cliente dovrebbe avere il proprio database che viene riempito leggendo i dati dai dispositivi di misurazione che appartengono al cliente.
Ho trovato soluzioni che suggeriscono di creare più contesti di database. Il problema con questo è che non è scalabile. Non conosco il numero di clienti / database in anticipo. Potrebbe essere 10, potrebbe essere 100.
Un'altra soluzione potrebbe essere quella di creare applicazioni separate in IIS (per semplicità parleremo solo di Windows e IIS). Ogni applicazione avrà il proprio percorso e il proprio appettings.json che specifica la stringa di connessione al database. Il problema con questo è che ci vorrebbe molto spazio su disco per duplicare l'applicazione (autonoma) e un sacco di lavori di manutenzione.
Domande:
1) esiste un modo per creare dinamicamente un elenco di contesti di database, dati più stringhe di connessione nel mio appsettings.json?
2) esiste un modo per mantenere solo una installazione fisica in IIS ma avere più siti che ciascuno avvia l'applicazione con un diverso appsettings.json o magari un parametro di avvio che indica all'app quale stringa di connessione utilizzare da appsettings.json?
3) c'è un modo completamente diverso e migliore per raggiungerlo?
Vedo che questa è una vecchia domanda, ma è lo scenario con cui sto lavorando ora.
Se i tuoi inquilini hanno lo stesso schema e diversi database, il modo corretto sarebbe quello di avere un contesto principale per recuperare la stringa di connessione e un altro contesto per connettersi ai diversi titolari.
In uno scenario molto comune in cui si accede a un titolare o a un altro in base all'host, questa potrebbe essere la soluzione:
Recupera i dati per quel tenant
public class ContextTenant : IdentityDbContext<ApplicationUser,
ApplicationRole, int>, IContextTenant
{
private readonly string _tenantDatabase;
public ContextTenant(DbContextOptions<ContextTenant> options, ITenantProvider tenantProvider) : base(options)
{
_tenantDatabase = tenantProvider.GetTenantDatabase();
SeedData.Initialize(this);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseMySQL(_teanantDatabase);
base.OnConfiguring(optionsBuilder);
}
...
create DbSets
other operations
...
}
Quindi recuperare la stringa di connessione:
public class WebTenantProvider : ITenantProvider
{
private readonly string _tenantDatabase;
public WebClientProvider(IHttpContextAccessor httpAccessor, ContextMaster dataContext)
{
var host = httpAccessor.HttpContext.Request.Host.Host;
_tenantDatabase = dataContext.GetTenantDatabaseFromHost(host);
}
public string GetTenantDatabase()
{
return _tenantDatabase;
}
}
public interface ITenantProvider
{
string GetTenantDatabase();
}
Anche la tua seconda domanda è interessante, perché ho un altro problema qui. Le risorse di localizzazione delle mie app sono modificabili, le sto ottenendo invece dei file Regx dal database, quindi ogni titolare ha le sue risorse e può modificarle.
Potrebbe essere possibile avere una sola applicazione con tutti i file, ma avviare diverse istanze di tale applicazione per diversi host? Nel caso in cui ciò fosse possibile, non abbiamo bisogno della stringa di connessione poiché ogni istanza avrebbe tutto indipendente ...