Come leggere la stringa di connessione in .NET Core?


108

Voglio leggere solo una stringa di connessione da un file di configurazione e per questo aggiungere un file con il nome "appsettings.json" al mio progetto e aggiungere questo contenuto su di esso:

{
"ConnectionStrings": {
  "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-

 WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
    "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
    "Default": "Debug",
    "System": "Information",
    "Microsoft": "Information"
   }
 }
}

Su ASP.NET ho usato questo:

 var temp=ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString;

Ora come posso leggere "DefaultConnection" in C # e memorizzarlo su una variabile stringa in .NET Core?


Risposte:


101

Puoi farlo con il metodo di estensione GetConnectionString:

string conString = Microsoft
   .Extensions
   .Configuration
   .ConfigurationExtensions
   .GetConnectionString(this.Configuration, "DefaultConnection");

System.Console.WriteLine(conString);

o con una classe strutturata per DI:

public class SmtpConfig
{
    public string Server { get; set; }
    public string User { get; set; }
    public string Pass { get; set; }
    public int Port { get; set; }
}

Avviare:

public IConfigurationRoot Configuration { get; }


// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // http://developer.telerik.com/featured/new-configuration-model-asp-net-core/
    // services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));
    Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<SmtpConfig>(services, Configuration.GetSection("Smtp"));

E poi nel controller di casa:

public class HomeController : Controller
{

    public SmtpConfig SmtpConfig { get; }
    public HomeController(Microsoft.Extensions.Options.IOptions<SmtpConfig> smtpConfig)
    {
        SmtpConfig = smtpConfig.Value;
    } //Action Controller


    public IActionResult Index()
    {
        System.Console.WriteLine(SmtpConfig);
        return View();
    }

con questo in appsettings.json:

"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
},

"Smtp": {
    "Server": "0.0.0.1",
    "User": "user@company.com",
    "Pass": "123456789",
    "Port": "25"
  }

9
Configureè un metodo di estensione. Dovrebbe essere usato più comunemente in questo modo: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Certo, è più o meno la stessa cosa, ma penso che le persone non consapevoli inizieranno semplicemente a farlo nel modo "sbagliato", usando la linea non commentata, quindi forse è meglio rimuovere la linea. ;)
James Wilkins

@ James Wilkins: preoccupazioni molto valide. Tuttavia, in realtà preferisco questa notazione piuttosto che usarla come metodo di estensione: in questo modo so cosa viene fatto dove e posso copiare e incollare da 1 posto a un altro, senza problemi a causa della mancanza di spazi dei nomi di importazione. L'unico problema è che MS utilizza gli spazi dei nomi per la tassonomia invece della prevenzione delle collisioni di nomi, per questo motivo gli spazi dei nomi sono troppo lunghi. Inoltre, se rimuovi i namspace e utilizzi i metodi di estensione, lo stesso tipo di persone inizierà a lamentarsi della mancata compilazione del codice. Non tutti usano un IDE, quindi è meglio così.
Stefan Steiger

3
@ JedatKinports: No, solo iniezione. Anche se scrivessi un metodo statico, avresti comunque bisogno della configurazione. Tuttavia, potresti semplicemente leggere un file JSON / YAML manualmente. Ma ciò eliminerà le sovrascritture, come i segreti degli utenti o altri (ad esempio la configurazione dal registro).
Stefan Steiger

1
Ricevo un errore: "MyClass contiene una definizione per" Configurazione "..."
Robert Smith

3
A cosa si riferisce "this.Configuration" nella parte della stringa di connessione? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000

111

La risposta pubblicata va bene ma non ha risposto direttamente alla stessa domanda che avevo sulla lettura in una stringa di connessione. Attraverso molte ricerche ho trovato un modo leggermente più semplice per farlo.

In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ...
    // Add the whole configuration object here.
    services.AddSingleton<IConfiguration>(Configuration);
}

Nel tuo controller aggiungi un campo per la configurazione e un parametro per essa su un costruttore

private readonly IConfiguration configuration;

public HomeController(IConfiguration config) 
{
    configuration = config;
}

Ora più avanti nel tuo codice di visualizzazione puoi accedervi come:

connectionString = configuration.GetConnectionString("DefaultConnection");

2
Non lo farei così. Se lavori senza entity framework, è meglio registrare una connection factory come singleton, ad esempio per usarla con dapper. Puoi ancora esporre una proprietà connectionString se necessario, ma scommetto che non sarebbe necessario nel 99% dei casi.
Stefan Steiger

2
Ma come accedere alla configurazione nei modelli invece che nel controller?
Tanmay

2
Più leggo e provo, più mi rendo conto che ottenere una stringa di connessione è un'impresa importante. Ottengo solo valori nulli, non importa cosa provo.
MC9000

7
Si. Troppi scienziati informatici che creano enormi frutti ad alto appeso solo per dire "Hello World". Incredibile. Entropia al meglio.
JustJohn

2
@ JustJohn: Capisco il tuo reclamo, ma il design corretto è testabile, e questo significa che devi passare le dipendenze nel costruttore, altrimenti la tua applicazione / framework non è testabile. Anche questo è un design corretto, in quanto puoi semplicemente sostituire un componente con un altro, senza dover cambiare un sacco di codice. Se non vuoi passare 100 argomenti in giro, puoi anche passare System.IServiceProvider alla classe, quindi puoi recuperare le dipendenze lì. Ma l'altro lato della medaglia è che questo comporta una complessità aggiuntiva.
Stefan Steiger,

18

Vedere il collegamento per maggiori informazioni: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-strings

JSON

    {
      "ConnectionStrings": {
        "BloggingDatabase": "Server=(localdb)\\mssqllocaldb;Database=EFGetStarted.ConsoleApp.NewDb;Trusted_Connection=True;"
      },
    }

C # Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<BloggingContext>(options =>
        options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}

EDIT: aspnetcore, a partire dalla 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1


Perché il file JSON dovrebbe avere ConnectionStringsinvece di ConnectionString? Perché quando ho usato ConnectionString, poi ci sto diventando nullo.
Vijay

@Vijay Prova a utilizzare il metodo prescritto, quindi;) Si prega di vedere il collegamento allegato.
markokstate

1
Questo metodo sembra obsoleto al Microsoft.Extensions.Configuration(3.1.5)
Ju66ernaut

7

Il modo in cui ho trovato per risolvere questo problema è stato utilizzare AddJsonFile in un builder all'avvio (che gli consente di trovare la configurazione memorizzata nel file appsettings.json) e quindi utilizzarlo per impostare una variabile _config privata

public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        _config = builder.Build();
    }

E poi potrei impostare la stringa di configurazione come segue:

var connectionString = _config.GetConnectionString("DbContextSettings:ConnectionString"); 

Questo è su dotnet core 1.1


5
come posso accedere a _config nel mio controllo?
soleggiato

Aggiungendolo al contenitore DI in ConfigureServices in Startup.cs.
Stefan Steiger

3

ASP.NET Core ( nel mio caso 3.1 ) ci fornisce iniezioni di Constructor nei controller , quindi puoi semplicemente aggiungere il seguente costruttore:

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    private readonly IConfiguration m_config;

    public TestController(IConfiguration config)
    {
        m_config = config;
    }

    [HttpGet]
    public string Get()
    {
        //you can get connection string as follows
        string connectionString = m_config.GetConnectionString("Default")
    }
}

Ecco come potrebbe apparire appsettings.json:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}

0

C'è un altro approccio. Nel mio esempio si vede una logica di business nella classe di repository che uso con l'inserimento delle dipendenze in ASP .NET MVC Core 3.1.

E qui voglio ottenere connectiongStringper quella logica di business perché probabilmente un altro repository avrà accesso a un altro database.

Questo modello consente di accedere a database diversi nello stesso repository di logica aziendale.

C #

public interface IStatsRepository
{
            IEnumerable<FederalDistrict> FederalDistricts();
}

class StatsRepository : IStatsRepository
{
   private readonly DbContextOptionsBuilder<EFCoreTestContext>
                optionsBuilder = new DbContextOptionsBuilder<EFCoreTestContext>();
   private readonly IConfigurationRoot configurationRoot;

   public StatsRepository()
   {
       IConfigurationBuilder configurationBuilder = new ConfigurationBuilder().SetBasePath(Environment.CurrentDirectory)
           .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true);
       configurationRoot = configurationBuilder.Build();
   }

   public IEnumerable<FederalDistrict> FederalDistricts()
   {
        var conn = configurationRoot.GetConnectionString("EFCoreTestContext");
        optionsBuilder.UseSqlServer(conn);

        using (var ctx = new EFCoreTestContext(optionsBuilder.Options))
        { 
            return ctx.FederalDistricts.Include(x => x.FederalSubjects).ToList();
        }
    }
}

appsettings.json

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "EFCoreTestContext": "Data Source=DESKTOP-GNJKL2V\\MSSQLSERVER2014;Database=Test;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

-1

ho una libreria di accesso ai dati che funziona sia con .net core che con .net framework.

il trucco stava nei progetti .net core per mantenere le stringhe di connessione in un file xml chiamato "app.config" (anche per progetti web), e contrassegnarlo come 'copia nella directory di output',

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <connectionStrings>
    <add name="conn1" connectionString="...." providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

ConfigurationManager.ConnectionStrings: leggerà la stringa di connessione.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;

Se stai usando .NET Core, è meglio adottare il suo modello di configurazione invece di shoehorning nel modello .NET Framework.
Simmetrico

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.