webentwicklung-frage-antwort-db.com.de

Laden Sie ConnectionString von appsettings.json herunter, anstatt in .NET Core 2.0 App fest codiert zu werden

Ich habe die folgende Klasse in der 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);
    }
}

Dies ist in Core 2.0 mit Migration erforderlich, wenn die Datenbank nicht vorhanden ist, und muss erstellt werden, wenn Sie update-database ausführen.
Migrationen können nach einem Upgrade auf ASP.NET Core 2.0 nicht erstellt werden.

Ich möchte ConnectionString nicht an zwei Stellen haben (hier und in appsettings.json), sondern nur in .json Ich habe also versucht zu ersetzen

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

mit

ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString

aber es funktioniert nicht, ich bekomme null wert.

UPDATE 1:
Nur um zu bemerken, dass das explizite Hinzufügen von .json in Core 2 nicht erforderlich ist, daher liegt das Problem nicht bei der Datei.
https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/

UPDATE 2:
Außerdem verwende ich bereits Configuration zum Senden von ConnectionString von .json an den Kontext:

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

Ich kann dies jedoch nicht für ToDoContextFactory verwenden, da es keine Konfiguration hat und ToDoContextFactory von Migrationen verwendet wird, sodass die App überhaupt nicht ausgeführt wird.

LÖSUNG: Basierend auf der Antwort von @JRB habe ich es so funktionieren lassen:

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

SCHRITT 1: Fügen Sie Folgendes in OnConfiguring () ein

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

SCHRITT 2: appsettings.json erstellen: 

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

SCHRITT 3: Kopieren Sie die Datei appsettings.json in das richtige Verzeichnis 

  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.        

Annahme: Sie haben bereits das Paket Microsoft.Extensions.Configuration.Json (erhalten Sie es von Nuget) in Ihr Projekt aufgenommen.

39
JRB

Es gibt tatsächlich ein Standardmuster, mit dem Sie dieses Ergebnis erzielen können, ohne IDesignTimeDbContextFactory implementieren und Konfigurationsdateien kopieren zu müssen.

Ausführliche Informationen finden Sie in this doc , in dem auch die anderen Methoden erläutert werden, mit denen das Framework versucht, Ihr DbContext zur Entwurfszeit zu instanziieren.

Insbesondere nutzen Sie einen neuen Hook, in diesem Fall eine statische Methode der Form public static IWebHost BuildWebHost(string[] args). Die Dokumentation impliziert etwas anderes, aber diese Methode kann sich in jeder Klasse befinden, in der sich Ihr Einstiegspunkt befindet ( see src ). Die Implementierung ist Teil der Anleitung im 1.x bis 2.x Migrationsdokument und was im Code nicht ganz offensichtlich ist, ist, dass der Aufruf von WebHost.CreateDefaultBuilder(args) verbindet unter anderem Ihre Konfiguration mit dem Standardmuster, mit dem neue Projekte beginnen. Das ist alles, was Sie benötigen, um die Konfiguration zu erhalten, die von den Entwurfszeitdiensten wie Migrationen verwendet wird.

Hier erfahren Sie mehr darüber, was tief im Inneren vor sich geht:

Wenn das Framework beim Hinzufügen einer Migration versucht, Ihr DbContext zu erstellen, fügt es first alle gefundenen IDesignTimeDbContextFactory -Implementierungen zu einer Sammlung von Factory-Methoden hinzu Das kann verwendet werden, um Ihren Kontext zu erstellen. Anschließend werden Ihre konfigurierten Dienste über den zuvor erläuterten statischen Hook abgerufen und sieht aus für alle Kontexttypen, die mit einem DbContextOptions (which) registriert wurden passiert in Ihrem Startup.ConfigureServices, wenn Sie AddDbContext oder AddDbContextPool) verwenden und diese Fabriken hinzufügen. Schließlich sucht in der Assembly nach allen DbContext abgeleiteten Klassen und erstellt eine Factory-Methode, die nur Activator.CreateInstance Als letzten Hagel Mary aufruft.

Die Rangfolge, die das Framework verwendet, ist dieselbe wie oben. Wenn Sie also IDesignTimeDbContextFactory implementiert haben, wird der oben erwähnte Hook überschrieben. Für die meisten gängigen Szenarien benötigen Sie jedoch nicht IDesignTimeDbContextFactory.

4
Erikest

In ASPNET Core machen Sie das in Startup.cs

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

wo Ihre Verbindung in appsettings.json definiert ist

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

Beispiel aus MS-Dokumenten

2
Roman Gudkov

Ich verstehe, dass dies als beantwortet markiert wurde, aber ich hatte ein kleines Problem, als ich an einem Projekt arbeitete, bei dem mein EF Core Data Access Layer in einem .DLL-Projekt vom Rest des Projekts getrennt ist Mein Projekt, API, Auth und Web und am liebsten meine anderen Projekte, um auf dieses Datenprojekt zu verweisen. Und ich möchte nicht jedes Mal in das Datenprojekt kommen, um die Verbindungszeichenfolgen zu ändern.

SCHRITT 1: Fügen Sie dies in die OnConfiguring-Methode ein

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
      {
           var envName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
           IConfigurationRoot configuration = new ConfigurationBuilder()
                **.SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))**
                .AddJsonFile("appsettings.json", optional: false)
                .AddJsonFile($"appsettings.{envName}.json", optional: false)
                .Build();
           optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
      }

ANMERKUNG: .SetBasePath (Path.Combine (Directory.GetCurrentDirectory ()) Dies negiert oder macht die Notwendigkeit ungültig, die Datei in ein Verzeichnis zu kopieren, da ASP.NET CORE intelligent genug ist, um die richtige auszuwählen Datei. Auch die angegebene Umgebung wählt die richtige Datei aus, wenn das Gebäude für die Veröffentlichung oder Produktion ausgewählt wird, vorausgesetzt, die Prod-Umgebungsdatei ist ausgewählt.

SCHRITT 2: Erstellen Sie appsettings.json

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

}

BITTE: Referenz: Microsoft.Extensions.Configuration

1
Ismail Umar

Wie wäre es, wenn Sie es als dp-Injektion in diese Klasse übergeben?.

services.Configure<MyOptions>(Configuration);

klasse erstellen, um Json-Strings aufzunehmen:

public class MyOptions
{
    public MyOptions()
    {

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

Hinzufügen von Strings zur Json-Datei:

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

Übergeben Sie in Klassen, die diese Zeichenfolgen benötigen, als Konstruktor:

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. Fügen Sie den folgenden Code in die startup.cs-Datei ein.

    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. Verwenden Sie die GlobalProperties.DBConnection-Eigenschaft in der Context-Klasse.

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

Sie können dies auch in ASP.NET Core 2 tun, indem Sie die Verbindungszeichenfolge in Ihrer appSettings.json-Datei definieren. Dann geben Sie in Ihrem Startup.cs an, welche Verbindungszeichenfolge verwendet werden soll. 

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