Comment lire la chaîne de connexion dans .NET Core?

109

Je veux lire juste une chaîne de connexion à partir d'un fichier de configuration et pour cela ajouter un fichier avec le nom "appsettings.json" à mon projet et y ajouter ce contenu:

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

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

Sur ASP.NET, j'ai utilisé ceci:

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

Maintenant, comment puis-je lire "DefaultConnection" en C # et le stocker sur une variable de chaîne dans .NET Core?

motevalizadeh
la source

Réponses:

102

Vous pouvez le faire avec la méthode d'extension GetConnectionString:

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

System.Console.WriteLine(conString);

ou avec une classe structurée pour DI:

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

Commencez:

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

Et puis dans le home-controller:

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

avec ceci dans 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
la source
9
Configureest une méthode d'extension. Il devrait être utilisé le plus souvent comme ceci: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Bien sûr, c'est à peu près la même chose, mais je pense que les gens qui ne sont pas au courant commenceront simplement à le faire de la "mauvaise" façon, en utilisant la ligne non commentée, alors peut-être mieux de supprimer la ligne. ;)
James Wilkins
@James Wilkins: Des préoccupations très valables. Cependant, je préfère en fait cette notation à son utilisation comme méthode d'extension - de cette façon, je sais ce qui est fait où, et je peux copier-coller d'un endroit à un autre, sans avoir de problèmes à cause des espaces de noms d'importation manquants. Le seul problème est que MS utilise des espaces de noms pour la taxonomie au lieu de la prévention des collisions de noms - à cause de cela, les espaces de noms sont trop longs. De plus, si vous supprimez les espaces de noms et utilisez les méthodes d'extension, le même genre de personnes commencera à se plaindre du code non compilé. Tout le monde n'utilise pas d'EDI, c'est donc mieux ainsi.
Stefan Steiger
3
@JedatKinports: Non, seulement une injection. Même si vous écrivez une méthode statique, vous aurez toujours besoin de la configuration. Cependant, vous pouvez simplement lire un fichier JSON / YAML manuellement. Mais cela éliminera les écrasements, tels que les userecrets ou autres (par exemple la configuration à partir du registre).
Stefan Steiger
1
J'obtiens une erreur: "MyClass contient une définition pour 'Configuration' ..."
Robert Smith
3
À quoi fait référence "this.Configuration" dans la partie chaîne de connexion? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000
112

La réponse publiée est correcte mais n'a pas répondu directement à la même question que j'avais sur la lecture dans une chaîne de connexion. Grâce à de nombreuses recherches, j'ai trouvé un moyen un peu plus simple de le faire.

Dans Startup.cs

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

Dans votre contrôleur, ajoutez un champ pour la configuration et un paramètre pour celle-ci sur un constructeur

private readonly IConfiguration configuration;

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

Maintenant, plus tard dans votre code de vue, vous pouvez y accéder comme:

connectionString = configuration.GetConnectionString("DefaultConnection");
Brad Patton
la source
2
Je ne ferais pas ça comme ça. Si vous travaillez sans framework d'entité, vous feriez mieux d'enregistrer une fabrique de connexions en tant que singleton, par exemple à utiliser avec dapper. Vous pouvez alors toujours exposer une propriété connectionString si vous en avez besoin, mais je parie que cela ne serait pas nécessaire dans 99% des cas.
Stefan Steiger
2
Mais comment accéder à la configuration dans les modèles au lieu du contrôleur?
Tanmay
2
Plus je lis et j'essaye des choses, plus je me rends compte qu'obtenir une chaîne de connexion est une entreprise majeure. J'obtiens juste des valeurs nulles quoi que j'essaye.
MC9000
7
Ouais. Trop d'informaticiens créent d'énormes fruits suspendus juste pour dire "Hello World". Incroyable. L'entropie à son meilleur.
JustJohn
2
@JustJohn: Je comprends votre grief, mais une conception appropriée est testable, et cela signifie que vous devez passer des dépendances dans le constructeur, sinon votre application / framework n'est pas testable unitaire. C'est également une conception appropriée, car vous pouvez simplement remplacer un composant par un autre, sans avoir à changer beaucoup de code. Si vous ne souhaitez pas passer 100 arguments, vous pouvez également passer le System.IServiceProvider dans la classe, puis vous pouvez y récupérer les dépendances. Mais le revers de la médaille est que cela s'accompagne d'une complexité supplémentaire.
Stefan Steiger du
18

Voir le lien pour plus d'informations: 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, à partir de 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1

markokstate
la source
Pourquoi le fichier JSON devrait-il avoir ConnectionStringsau lieu de ConnectionString? Parce que quand j'ai utilisé ConnectionString, alors nous devenons nul.
Vijay
@Vijay Essayez alors d'utiliser la méthode prescrite;) Veuillez consulter le lien ci-joint.
markokstate
1
Cette méthode semble obsolète au Microsoft.Extensions.Configuration(3.1.5)
Ju66ernaut
7

La façon dont j'ai trouvé pour résoudre ce problème était d'utiliser AddJsonFile dans un constructeur au démarrage (ce qui lui permet de trouver la configuration stockée dans le fichier appsettings.json), puis de l'utiliser pour définir une variable _config privée

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

Et puis je pourrais définir la chaîne de configuration comme suit:

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

C'est sur dotnet core 1.1

Alex White
la source
5
comment puis-je accéder à _config dans mon contrôle?
ensoleillé le
En l'ajoutant au conteneur DI dans ConfigureServices dans Startup.cs.
Stefan Steiger
3

ASP.NET Core ( dans mon cas 3.1 ) nous fournit des injections de constructeur dans les contrôleurs , vous pouvez donc simplement ajouter le constructeur suivant:

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

Voici à quoi peut ressembler appsettings.json:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}
antonpv
la source
0

Il existe une autre approche. Dans mon exemple, vous voyez une logique métier dans la classe de référentiel que j'utilise avec l'injection de dépendances dans ASP .NET MVC Core 3.1.

Et ici, je veux obtenir connectiongStringcette logique métier car un autre référentiel aura probablement accès à une autre base de données.

Ce modèle vous permet, dans le même référentiel de logique métier, d'accéder à différentes bases de données.

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"
  }
}
Développeur
la source
-1

J'ai une bibliothèque d'accès aux données qui fonctionne à la fois avec .net core et .net framework.

l'astuce était dans les projets principaux .net de conserver les chaînes de connexion dans un fichier xml nommé "app.config" (également pour les projets Web), et de le marquer comme "copier dans le répertoire de sortie",

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

ConfigurationManager.ConnectionStrings - lira la chaîne de connexion.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
shaig
la source
Si vous utilisez .NET Core, il est préférable d'adopter son modèle de configuration au lieu de Shoehorning dans le modèle .NET Framework.
Simmetric