In una libreria di classi NET Core 2.1 ho un DbContext di Entity Framework Core 2.1:
public class AppContext : IdentityDbContext<User, Role, Int32> {
public AppContext(DbContextOptions options) : base(options) { }
}
Per eseguire le migrazioni nella libreria di classi avevo bisogno di aggiungere quanto segue:
public class ContextFactory : IDesignTimeDbContextFactory<Context> {
public Context CreateDbContext(String[] args) {
DbContextOptionsBuilder builder = new DbContextOptionsBuilder<Context>();
builder.UseSqlServer(@"Server=localhost;Database=db;User=sa;Password=pass;");
return new Context(builder.Options);
}
}
Con questo sono in grado di eseguire, sui comandi della libreria di classi come:
dotnet ef migrations add "InitialCommit"
dotnet ef database update
Ma come spostare la stringa di connessione in un file settings.json nella libreria di classi?
IDesignTimeDbContextFactory
, come suggerisce il nome, è strettamente per lo sviluppo. Generalmente non è necessario esternalizzare la stringa di connessione, perché dovrebbe essere abbastanza statica, anche in un ambiente di squadra. Detto questo, semmai, dovresti archiviarlo nei segreti degli utenti, perché di nuovo, questo è solo per lo sviluppo. L'uso dei segreti utente mantiene la stringa di connessione fuori dal controllo del codice sorgente, così gli sviluppatori del tuo team non si calpestano l'un l'altro con le stringhe di connessione reciproche.
var config = new ConfigurationBuilder()
.AddUserSecrets()
.Build();
var connectionString = config.GetConnectionString("Foo");
L'implementazione IDesignTimeDbContextFactory<>
viene eseguita tramite il processo di utilità EF. Questa è un'applicazione di console normale in cui è possibile utilizzare Console.Write()
e Console.Read()
per interagire con l'utente che esegue migrazioni e aggiornamenti. Ciò consente all'utente di inserire la propria stringa di connessione in fase di aggiornamento.
public class Builder : IDesignTimeDbContextFactory<AppContext>
{
public AppContext CreateDbContext(string[] args)
{
Console.Write("Enter your connection string: ");
var conStr = Console.ReadLine();
var options = new DbContextOptionsBuilder<AppContext>().UseSqlServer(conStr).Options;
return new AppContext(options);
}
}