¿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?


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": "user@company.com",
    "Pass": "123456789",
    "Port": "25"
  }

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

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


¿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


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

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

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

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.