¿Cómo leer la cadena de conexión en .NET Core?

108

Quiero leer solo una cadena de conexión de un archivo de configuración y para esto agregar un archivo con el nombre "appsettings.json" a mi proyecto y agregar este contenido en él:

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

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

En ASP.NET utilicé esto:

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

Ahora, ¿cómo puedo leer "DefaultConnection" en C # y almacenarlo en una variable de cadena en .NET Core?

motevalizadeh
fuente

Respuestas:

101

Puede hacer esto con el método de extensión GetConnectionString:

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

System.Console.WriteLine(conString);

o con una clase estructurada para DI:

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

Puesta en marcha:

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"));

Y luego en el controlador de 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 esto en appsettings.json:

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

"Smtp": {
    "Server": "0.0.0.1",
    "User": "[email protected]",
    "Pass": "123456789",
    "Port": "25"
  }
Stefan Steiger
fuente
9
Configurees un método de extensión. Debería usarse más comúnmente así: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Claro, es casi lo mismo, pero creo que las personas que no lo saben comenzarán a hacerlo de la manera "incorrecta", usando la línea sin comentar, así que quizás sea mejor eliminar la línea. ;)
James Wilkins
@James Wilkins: Preocupaciones muy válidas. Sin embargo, en realidad prefiero esta notación a usarla como método de extensión; de esta manera, sé qué se está haciendo y dónde y puedo copiar y pegar de un lugar a otro, sin tener problemas debido a la falta de espacios de nombres de importación. El único problema es que MS usa espacios de nombres para la taxonomía en lugar de la prevención de colisiones de nombres; por eso, los espacios de nombres son demasiado largos. Además, si elimina los namspaces y usa los métodos de extensión, el mismo tipo de personas comenzará a quejarse de que el código no se compila. No todo el mundo usa un IDE, por lo que es mejor así.
Stefan Steiger
3
@JedatKinports: No, solo inyección. Incluso si escribiera un método estático, aún necesitaría la configuración. Sin embargo, puede leer un archivo JSON / YAML manualmente. Pero eso eliminará las sobrescrituras, como los secretos del usuario u otros (por ejemplo, la configuración del registro).
Stefan Steiger
1
Recibo un error: "MyClass contiene una definición de 'Configuración' ..."
Robert Smith
3
¿A qué se refiere "this.Configuration" en la parte de la cadena de conexión? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000
111

La respuesta publicada está bien, pero no respondió directamente a la misma pregunta que tenía sobre la lectura en una cadena de conexión. A través de muchas búsquedas, encontré una forma un poco más sencilla de hacer esto.

En Startup.cs

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

En su controlador, agregue un campo para la configuración y un parámetro para él en un constructor

private readonly IConfiguration configuration;

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

Ahora, más adelante en su código de vista, puede acceder a él como:

connectionString = configuration.GetConnectionString("DefaultConnection");
Brad Patton
fuente
2
No lo haría así. Si trabaja sin un marco de entidad, es mejor que registre una fábrica de conexiones como singleton, por ejemplo, para usar con dapper. Luego, aún puede exponer una propiedad connectionString si lo necesita, pero apuesto a que no sería necesario en el 99% de los casos.
Stefan Steiger
2
Pero, ¿cómo acceder a la configuración en modelos en lugar de al controlador?
Tanmay
2
Cuanto más leo y pruebo cosas, más me doy cuenta de que obtener una cadena de conexión es una tarea importante. Solo obtengo nulos sin importar lo que intente.
MC9000
7
Si. Demasiados científicos informáticos creando enormes frutas colgantes solo para decir "Hola mundo". Increíble. Entropía en su máxima expresión.
JustJohn
2
@JustJohn: Entiendo su queja, pero el diseño adecuado se puede probar, y eso significa que debe pasar dependencias en el constructor, de lo contrario, su aplicación / marco no se puede probar por unidades. Este también es un diseño adecuado, ya que puede reemplazar un componente por otro sin tener que cambiar mucho código. Si no desea pasar 100 argumentos, también puede pasar System.IServiceProvider a la clase, luego puede buscar las dependencias allí. Pero la otra cara de la moneda es que esto conlleva una mayor complejidad.
Stefan Steiger
18

Consulte el enlace para obtener más información: https://docs.microsoft.com/en-us/ef/core/misiverse/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")));
}

EDITAR: aspnetcore, a partir de 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1

markokstate
fuente
¿Por qué debería tener el archivo JSON en ConnectionStringslugar de ConnectionString? Porque cuando utilicé ConnectionString, entonces obtendré nulo.
Vijay
@Vijay Intente usar el método prescrito entonces;) Consulte el enlace adjunto.
markokstate
1
Este método parece Microsoft.Extensions.Configuration
obsoleto a
7

La forma en que encontré para resolver esto fue usar AddJsonFile en un constructor en el inicio (que le permite encontrar la configuración almacenada en el archivo appsettings.json) y luego usarla para establecer una variable _config privada

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();
    }

Y luego podría configurar la cadena de configuración de la siguiente manera:

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

Esto está en dotnet core 1.1

Alex blanco
fuente
5
¿Cómo puedo acceder a _config en mi control?
soleado
Agregándolo al contenedor DI en ConfigureServices en Startup.cs.
Stefan Steiger
3

ASP.NET Core ( en mi caso 3.1 ) nos proporciona inyecciones de constructor en controladores , por lo que simplemente puede agregar el siguiente constructor:

[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")
    }
}

Aquí lo que puede parecer appsettings.json:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}
antonpv
fuente
0

Hay otro enfoque. En mi ejemplo, ve algo de lógica empresarial en la clase de repositorio que utilizo con la inyección de dependencia en ASP .NET MVC Core 3.1.

Y aquí quiero obtener connectiongStringesa lógica empresarial porque probablemente otro repositorio tendrá acceso a otra base de datos.

Este patrón le permite en el mismo repositorio de lógica empresarial tener acceso a diferentes bases de datos.

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"
  }
}
Desarrollador
fuente
-1

Tengo una biblioteca de acceso a datos que funciona con .net core y .net framework.

el truco estaba en los proyectos principales de .net para mantener las cadenas de conexión en un archivo xml llamado "app.config" (también para proyectos web), y marcarlo como 'copiar al directorio de salida',

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

ConfigurationManager.ConnectionStrings: leerá la cadena de conexión.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
shaig
fuente
Si está utilizando .NET Core, es mejor adoptar su patrón de configuración en lugar de calzar en el patrón de .NET Framework.
Simmetric