web-dev-qa-db-fra.com

Obtenez ConnectionString à partir de appsettings.json au lieu d'être codé en dur dans l'application .NET Core 2.0

J'ai la classe suivante dans NET Core2.0 App.

// required when local database does not exist or was deleted
public class ToDoContextFactory : IDesignTimeDbContextFactory<AppContext>
{
    public AppContext CreateDbContext(string[] args)
    {
        var builder = new DbContextOptionsBuilder<AppContext>();
        builder.UseSqlServer("Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true");
        return new AppContext(builder.Options);
    }
}

Ceci est requis dans Core 2.0 avec la migration lorsque la base de données n'existe pas et doit être créé lors de l'exécution de update-database.
Impossible de créer des migrations après la mise à niveau vers ASP.NET Core 2.0

Je voudrais ne pas avoir ConnectionString à 2 endroits (ici et dans appsettings.json) mais seulement dans .json Alors j'ai essayé de remplacer

"Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true"

avec

ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString

mais ça ne marche pas, j'obtiens une valeur nulle.

MISE À JOUR 1:
Juste pour noter que l’ajout explicite de .json n’est pas nécessaire dans le Core 2, le problème n’est donc pas lié au fichier.
https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/

MISE À JOUR 2:
De plus, j'utilise déjà Configuration pour envoyer ConnectionString de .json au contexte:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

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

Mais je ne peux pas l'utiliser pour ToDoContextFactory car il n'a pas de configuration et que ToDoContextFactory est utilisé par les migrations, de sorte que l'application ne s'exécute pas du tout.

SOLUTION: D'après la réponse de @JRB, je l'ai fait fonctionner comme suit:

public AppContext CreateDbContext(string[] args)
{
    string projectPath = AppDomain.CurrentDomain.BaseDirectory.Split(new String[] { @"bin\" }, StringSplitOptions.None)[0];
    IConfigurationRoot configuration = new ConfigurationBuilder()
        .SetBasePath(projectPath)
        .AddJsonFile("appsettings.json")
        .Build();
    string connectionString = configuration.GetConnectionString("DefaultConnection");

    var builder = new DbContextOptionsBuilder<AppContext>();
    builder.UseSqlServer(connectionString);

    return new AppContext(builder.Options);
}
29
borisdj

ÉTAPE 1: inclure les éléments suivants dans OnConfiguring ()

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
            .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
            .AddJsonFile("appsettings.json")
            .Build();
        optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
    }

ÉTAPE 2: Créer appsettings.json: 

  {
    "ConnectionStrings": {       
      "DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"        
    } 
  }

ÉTAPE 3: Copiez le fichier appsettings.json dans le répertoire approprié. 

  Hard copy appsettings.json.config to the directory specified in the AppDomain.CurrentDomain.BaseDirectory directory. 
  Use your debugger to find out which directory that is.        

Hypothèse: vous avez déjà inclus le package Microsoft.Extensions.Configuration.Json (récupérez-le auprès de Nuget) dans votre projet.

39
JRB

Il existe en fait un modèle par défaut que vous pouvez utiliser pour obtenir ce résultat sans avoir à implémenter IDesignTimeDbContextFactory et à copier les fichiers de configuration.

Il est détaillé dans le présent document , qui traite également des autres moyens utilisés par le cadre pour tenter d’instancier votre DbContext au moment de la conception.

Plus précisément, vous exploitez un nouveau hook, dans ce cas une méthode statique de la forme public static IWebHost BuildWebHost(string[] args). La documentation implique le contraire, mais cette méthode peut vivre dans n'importe quelle classe hébergeant votre point d'entrée ( voir src ). Cette implémentation fait partie des recommandations du document de migration 1.x à 2.x et ce qui n'est pas complètement évident en regardant le code, c'est que l'appel à WebHost.CreateDefaultBuilder(args) consiste, entre autres, à connecter votre configuration dans le modèle par défaut. que les nouveaux projets commencent par. C'est tout ce dont vous avez besoin pour que la configuration soit utilisée par les services de conception, tels que les migrations.

Voici plus de détails sur ce qui se passe au fond: 

Lors de l'ajout d'une migration, lorsque le framework tente de créer votre DbContext, il en premier ajoute toutes les implémentations IDesignTimeDbContextFactory qu'il trouve à une collection de méthodes d'usine pouvant être utilisées pour créer votre contexte. hook discuté précédemment et cherche pour tous les types de contexte enregistrés avec une DbContextOptions (ce qui se produit dans votre Startup.ConfigureServices lorsque vous utilisez AddDbContext ou AddDbContextPool) et ajoute ces fabriques. Enfin, il recherche dans l’Assembly toutes les classes dérivées DbContext et crée une méthode fabrique qui appelle simplement Activator.CreateInstance en tant que final heal mary. 

L'ordre de priorité utilisé par le cadre est le même que ci-dessus. Ainsi, si vous avez implémenté IDesignTimeDbContextFactory, il remplacera le hook mentionné ci-dessus. Cependant, dans la plupart des scénarios courants, vous n'avez pas besoin de IDesignTimeDbContextFactory.

4
Erikest

Dans ASPNET Core, vous le faites dans Startup.cs

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

où votre connexion est définie dans appsettings.json

{
  "ConnectionStrings": {
    "BloggingDatabase": "..."
  },
}

Exemple tiré de MS docs

2
Roman Gudkov

Que diriez-vous de le passer sous forme d'injection dp dans cette classe?

services.Configure<MyOptions>(Configuration);

créer une classe pour contenir des chaînes JSON:

public class MyOptions
{
    public MyOptions()
    {

    }
    public string Option1 { get; set; }
    public string Option2 { get; set; }
}    

Ajouter des chaînes au fichier json:

"option1": "somestring",
"option2": "someothersecretstring"

Dans les classes qui ont besoin de ces chaînes, passez en tant que constructeur:

public class SomeClass
{
 private readonly MyOptions _options;

    public SomeClass(IOptions<MyOptions> options)
    {
        _options = options.Value;           
    }    

 public void UseStrings()
 {
   var option1 = _options.Option1;
    var option2 = _options.Option2;
 //code
 }
}
1
Johan Herstad
  1. Ajoutez le code suivant dans le fichier startup.cs.

    public void ConfigureServices(IServiceCollection services)
    {
        string con = Configuration.GetConnectionString("DBConnection");
        services.AddMvc();
        GlobalProperties.DBConnection = con;//DBConnection is a user defined static property of GlobalProperties class
    }
    
  2. Utilisez la propriété GlobalProperties.DBConnection dans la classe Context.

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {  
              optionsBuilder.UseSqlServer(GlobalProperties.DBConnection);
        }
    }
    
0
shravan sangishetti

Vous pouvez également le faire dans ASP.NET Core 2 en définissant la chaîne de connexion dans votre fichier appSettings.json. Ensuite, dans votre Startup.cs, vous spécifiez la chaîne de connexion à utiliser. 

appSettings.json

{
    "connectionStrings": {
        "YourDBConnectionString": "Server=(localdb)\\mssqllocaldb;Database=YourDB;Trusted_Connection=True"
    }
}

Startup.cs

public static IConfiguration Configuration { get; private set;}

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}
var connectionString = Configuration["connectionStrings:YourDBConnectionString"];
services.AddDbContext<YourDbContext>(x => x.UseSqlServer(connectionString));
0
Jonathan Kittell