Passare la stringa di connessione dell’applicazione in una libreria di classi del repository in ASP.NET 5 utilizzando IConfigurationRoot

Ho un’applicazione Web MVC ASP.NET 5 e in Startup.cs vedo che la proprietà pubblica

IConfigurationRoot Configuration 

è impostato su builder.Build();

In tutta l’applicazione Web MVC posso semplicemente farlo

 Startup.Configuration["Data:DefaultConnection:ConnectionString"] 

per ottenere la stringa conn dal file appsettings.json .

Come posso ottenere la stringa di connessione specificata in ASP.NET 5 MVC appsettings.json passata alla mia libreria di repository utilizzando l’iniezione del costruttore?

AGGIORNARE:
Ecco il repository di base ereditato da tutti gli altri repository (come potete vedere ho una stringa di connessione hardcoded qui per ora):

 public class BaseRepo { public static string ConnectionString = "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;"; public static SqlConnection GetOpenConnection() { var cs = ConnectionString; var connection = new SqlConnection(cs); connection.Open(); return connection; } } 

Nella mia applicazione web asp.net 5 nel mio file appsettings.json ho il seguente che equivale ad aggiungere una stringa di connessione a un web.config in una webapp .net 4.5:

  "Data": { "DefaultConnection": { "ConnectionString": "Server=MYSERVER;Database=MYDATABASE;Trusted_Connection=True;" } } 

Inoltre nella mia applicazione web asp.net 5 ho il seguente codice predefinito nel mio Startup.cs che carica la configurazione dei siti in una proprietà pubblica di tipo IConfigurationRoot:

  public IConfigurationRoot Configuration { get; set; } // Class Constructor public Startup(IHostingEnvironment env) { // Set up configuration sources. var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); if (env.IsDevelopment()) { // For more details on using the user secret store see http://go.microsoft.com/fwlink/?LinkID=532709 builder.AddUserSecrets(); } builder.AddEnvironmentVariables(); Configuration = builder.Build(); } 

Ora nella mia applicazione web asp.net se desidero accedere ad una qualsiasi delle app posso fare le seguenti cose: Startup.Configuration["Data:DefaultConnection:ConnectionString"]

Ma sfortunatamente non posso farlo dalla mia biblioteca di class ..

Se qualcuno vuole provare a capirlo, ecco i passi da eseguire:

  1. Creare una nuova app Web MVC ASP.NET 5.
  2. Aggiungere un altro progetto di tipo Libreria di classi (pacchetto) al progetto.
  3. Scopri come trasferire le app dell’app dall’app MVC ASP.NET 5 alla libreria di classi

Dopo l’aggiornamento non riesco ancora a capirlo. Ecco il mio codice:

 public class BaseRepo { private readonly IConfigurationRoot config; public BaseRepo(IConfigurationRoot config) { this.config = config; } } 

Questa dichiarazione di class non funziona poiché BaseRepo richiede ora un parametro costruttore.

 public class CustomerRepo : BaseRepository, ICustomerRepo { public Customer Find(int id) { using (var connection = GetOpenConnection()) { ... } } } 

nel tuo file Startup.cs aggiungi il seguente metodo

 public void ConfigureServices(IServiceCollection services) { services.AddSingleton(_ => Configuration); } 

quindi aggiorna la tua class BaseRepo in questo modo

 public class BaseRepo { private readonly IConfiguration config; public BaseRepo(IConfiguration config) { this.config = config; } public SqlConnection GetOpenConnection() { string cs = config["Data:DefaultConnection:ConnectionString"]; SqlConnection connection = new SqlConnection(cs); connection.Open(); return connection; } } 

ASP.NET offre il proprio modo per aggirare le impostazioni di configurazione.

Supponiamo di avere questo nel tuo appSettings.json:

 { "Config": { "Setting1": 1, "Setting2": "SO" } } 

Allora hai bisogno di una class come questa:

 public class MyConfiguration { public int Setting1 { get; set; } public string Setting2 { get; set; } } 

Ciò consente di configurare il servizio con questa configurazione aggiungendo la seguente riga

 services.Configure(Configuration.GetSection("Config")); 

ConfigureServices .

È quindi ansible iniettare la configurazione nei costruttori attenendosi alla seguente procedura:

 public class SomeController : Controller { private readonly IOptions config; public ServiceLocatorController(IOptions config) { this.config = config; } [HttpGet] public IActionResult Get() { return new HttpOkObjectResult(config.Value); } } 

Questo esempio è per i controller. Ma puoi fare lo stesso con altri livelli della tua applicazione.

Ho un costruttore nella mia class repository che accetta la stringa di connessione db come parametro. Questo funziona per me quando aggiungo il mio repository per l’iniezione. In ConfigureServies () del file startup.cs aggiungere questo:

 services.AddScoped(c => new Repos(Configuration["DbConnections:ConnStr1"])); 

IRepos.cs è l’interfaccia, Repos.cs è la class che lo implementa. E, naturalmente, la configurazione è solo un riferimento all’object IConfigurationRoot creato.

Se ConfigureServices nel file startUp.cs del progetto contiene

 services.AddEntityFramework() .AddSqlServer() .AddDbContext(options => options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"])); 

e il file cs del repository sta eseguendo un’iniezione del costruttore come mostrato di seguito

 public class MyRepo : IRepo { private readonly YourDbContext dbContext; public MyRepo(YourDbContext ctx) { dbContext = ctx; } } 

YourDbContext verrà risolto automaticamente.

Esiste già un metodo di estensione che è ansible utilizzare per ottenere stringhe di connessione specificatamente da aspsettings.json.

  1. Definisci le tue stringhe di connessione in appsettings.json in questo modo:

      { "ConnectionStrings": { "Local": "Data source=.\\SQLExpress;Initial Catalog=.......", "Test:": "Data source=your-server;......" }, "Logging": { "IncludeScopes": false, "LogLevel": { "Default": "Debug", "System": "Information", "Microsoft": "Information" } } } 
  2. Nel tuo public void ConfigureServices(IServiceCollection services) all’interno del tuo Startup.cs , puoi ottenere la stringa di connessione in questo modo:

     var connectionString = this.Configuration.GetConnectionString("Local"); 
  3. L’estensione GetConnectionString da Microsoft.Extensions.Configuration .
  4. Godere 🙂

AGGIORNARE

All’inizio non volevo entrare nei dettagli perché la domanda qui era già stata contrassegnata come risposta. Ma immagino di poter mostrare i miei 2 centesimi qui.

Se hai bisogno dell’intero object IConfigurationRoot immesso nei controller, @Chrono ha mostrato la strada giusta.

Se non è necessario l’intero object, è sufficiente ottenere la stringa di connessione, passarla nel DbContext all’interno della chiamata ConfigureServices() e iniettare DbContext in Controller. @Prashant Lakhlani lo ha mostrato correttamente.

Sto solo dicendo, nel post @Prashant Lakhlani, puoi usare GetConnectionString estensione GetConnectionString per pulire un po ‘il codice.

Quello di cui hai bisogno è creare una class nel progetto della libreria di classi per accedere al progetto appettings.json nel sito web e restituire la stringa di connessione.

 { private static string _connectionString; public static string GetConnectionString() { if (string.IsNullOrEmpty(_connectionString)) { var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json"); Configuration = builder.Build(); _connectionString = Configuration.Get("Data:MyDb:ConnectionString"); } return _connectionString; } public static IConfigurationRoot Configuration { get; set; } } 

Un approccio leggermente diverso sarebbe quello di creare una class statica nella libreria di classi su cui si chiama un metodo dal metodo Configure(..) in Startup.cs :

 public void Configure(IApplicationBuilder app, IHostingEnvironment env) { ... ConnectionManager.SetConfig(Configuration); } 

In questo caso, ho aggiunto Configurazione come Singleton in ConfigureServices :

 services.AddSingleton(_ => Configuration); 

Il mio ConnectionManager presenta così:

 public class ConnectionManager { private static IConfiguration currentConfig; public static void SetConfig(IConfiguration configuration) { currentConfig = configuration; } ///  /// Get a connection to the database. ///  public static SqlConnection GetConnection { get { string connectionString = currentConfig.GetConnectionString("MyConnection"); // Create a new connection for each query. SqlConnection connection = new SqlConnection(connectionString); return connection; } } } 

Questo può o non può avere alcuni problemi riguardanti la vita degli oggetti e così via, e io non sono certamente un fan delle classi static , ma per quanto posso dire è un approccio praticabile. Invece di passare alla Configuration puoi anche estrarre ConnectionString dal file di configurazione e inviarlo solo.