Wie lese ich eine Verbindungszeichenfolge in .NET Core?

108

Ich möchte nur eine Verbindungszeichenfolge aus einer Konfigurationsdatei lesen und dazu eine Datei mit dem Namen "appsettings.json" zu meinem Projekt hinzufügen und diesen Inhalt hinzufügen:

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

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

Unter ASP.NET habe ich Folgendes verwendet:

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

Wie kann ich nun "DefaultConnection" in C # lesen und in einer Zeichenfolgenvariablen in .NET Core speichern?

Motevalizadeh
quelle

Antworten:

101

Sie können dies mit der GetConnectionString-Erweiterungsmethode tun:

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

System.Console.WriteLine(conString);

oder mit einer strukturierten Klasse für DI:

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

Anfang:

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

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

mit diesem in 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
quelle
9
Configureist eine Erweiterungsmethode. Es sollte am häufigsten so verwendet werden: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Sicher, es ist fast dasselbe, aber ich denke, Leute, die sich nicht bewusst sind, werden es einfach "falsch" machen, indem sie die unkommentierte Linie verwenden, also vielleicht am besten, um die Linie zu entfernen. ;)
James Wilkins
@ James Wilkins: Sehr berechtigte Bedenken. Tatsächlich bevorzuge ich diese Notation jedoch gegenüber der Verwendung als Erweiterungsmethode. Auf diese Weise weiß ich, was wo getan wird, und kann sie von einem Ort zum anderen kopieren und einfügen, ohne dass Probleme aufgrund fehlender Import-Namespaces auftreten. Das einzige Problem ist, dass MS Namespaces für die Taxonomie anstelle der Verhinderung von Namenskollisionen verwendet. Aus diesem Grund sind die Namespaces zu lang. Wenn Sie die Namensräume entfernen und die Erweiterungsmethoden verwenden, beschweren sich dieselben Personen über den nicht kompilierten Code. Nicht jeder verwendet eine IDE, daher ist es auf diese Weise besser.
Stefan Steiger
3
@JedatKinports: Nein, nur Injektion. Selbst wenn Sie eine statische Methode schreiben würden, benötigen Sie die Konfiguration. Sie können eine JSON / YAML-Datei jedoch auch manuell lesen. Dadurch werden jedoch Überschreibungen wie Benutzergeheimnisse oder andere (z. B. Konfiguration aus der Registrierung) vermieden.
Stefan Steiger
1
Ich erhalte eine Fehlermeldung: "MyClass enthält eine Definition für 'Konfiguration' ..."
Robert Smith
3
Worauf bezieht sich "this.Configuration" im Verbindungszeichenfolgenteil? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000
111

Die gepostete Antwort ist in Ordnung, hat aber nicht direkt die gleiche Frage beantwortet, die ich zum Lesen einer Verbindungszeichenfolge hatte. Durch viel Suchen fand ich einen etwas einfacheren Weg, dies zu tun.

In Startup.cs

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

Fügen Sie in Ihrem Controller ein Feld für die Konfiguration und einen Parameter dafür in einem Konstruktor hinzu

private readonly IConfiguration configuration;

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

Jetzt später in Ihrem Ansichtscode können Sie wie folgt darauf zugreifen:

connectionString = configuration.GetConnectionString("DefaultConnection");
Brad Patton
quelle
2
Würde es nicht so machen. Wenn Sie ohne Entity Framework arbeiten, registrieren Sie eine Verbindungsfactory besser als Singleton, z. B. zur Verwendung mit Dapper. Sie können dann bei Bedarf immer noch eine connectionString-Eigenschaft verfügbar machen, aber ich wette, dass dies in 99% der Fälle nicht erforderlich ist.
Stefan Steiger
2
Aber wie kann man auf die Konfiguration in Modellen anstatt auf den Controller zugreifen?
Tanmay
2
Je mehr ich Dinge lese und ausprobiere, desto mehr wird mir klar, dass es ein großes Unterfangen ist, eine Verbindungszeichenfolge zu erhalten. Ich bekomme nur Nullen, egal was ich versuche.
MC9000
7
Ja. Zu viele Informatiker kreieren riesige, hoch hängende Früchte, nur um "Hallo Welt" zu sagen. Unglaublich. Entropie vom Feinsten.
JustJohn
1
@JustJohn: Ich verstehe Ihre Beschwerde, aber das richtige Design ist testbar, und das bedeutet, dass Sie Abhängigkeiten im Konstruktor übergeben müssen, sonst ist Ihre Anwendung / Ihr Framework nicht auf Einheiten testbar. Dies ist auch ein korrektes Design, da Sie einfach eine Komponente durch eine andere ersetzen können, ohne eine ganze Menge Code ändern zu müssen. Wenn Sie nicht 100 Argumente übergeben möchten, können Sie auch den System.IServiceProvider an die Klasse übergeben und dort die Abhängigkeiten abrufen. Die andere Seite der Medaille ist jedoch, dass dies mit einer zusätzlichen Komplexität verbunden ist.
Stefan Steiger
18

Weitere Informationen finden Sie unter dem Link: 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")));
}

BEARBEITEN: aspnetcore, ab 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1

Markokstate
quelle
Warum sollte JSON-Datei ConnectionStringsstatt haben ConnectionString? Denn wenn ich verwendet habe ConnectionString, dann bekomme ich null.
Vijay
@ Vijay Versuchen Sie es dann mit der vorgeschriebenen Methode;) Bitte beachten Sie den beigefügten Link.
Markokstate
1
Diese Methode scheint ab Microsoft.Extensions.Configuration(3.1.5)
veraltet zu sein
7

Um dies zu beheben, habe ich AddJsonFile in einem Builder beim Start verwendet (wodurch die in der Datei appsettings.json gespeicherte Konfiguration gefunden werden kann) und anschließend eine private Variable _config festgelegt

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

Und dann könnte ich die Konfigurationszeichenfolge wie folgt einstellen:

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

Dies ist auf Dotnet Core 1.1

Alex White
quelle
5
Wie kann ich in meiner Steuerung auf _config zugreifen?
sonnig
Durch Hinzufügen zum DI-Container in ConfigureServices in Startup.cs.
Stefan Steiger
3

ASP.NET Core ( in meinem Fall 3.1 ) bietet uns Konstruktorinjektionen in Controller , sodass Sie einfach den folgenden Konstruktor hinzufügen können:

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

So könnte appsettings.json aussehen:

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

Es gibt einen anderen Ansatz. In meinem Beispiel sehen Sie eine Geschäftslogik in der Repository-Klasse, die ich mit der Abhängigkeitsinjektion in ASP .NET MVC Core 3.1 verwende.

Und hier möchte ich connectiongStringauf diese Geschäftslogik eingehen, da wahrscheinlich ein anderes Repository überhaupt Zugriff auf eine andere Datenbank hat.

Mit diesem Muster haben Sie im selben Geschäftslogik-Repository Zugriff auf verschiedene Datenbanken.

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"
  }
}
Entwickler
quelle
-1

Ich habe eine Datenzugriffsbibliothek, die sowohl mit .net Core als auch .net Framework funktioniert.

In .net-Kernprojekten bestand der Trick darin, die Verbindungszeichenfolgen in einer XML-Datei mit dem Namen "app.config" (auch für Webprojekte) zu speichern und als "In Ausgabeverzeichnis kopieren" zu markieren.

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

ConfigurationManager.ConnectionStrings - liest die Verbindungszeichenfolge.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
shaig
quelle
Wenn Sie .NET Core verwenden, ist es am besten, das Konfigurationsmuster zu übernehmen, anstatt es in das .NET Framework-Muster einzufügen.
Simmetric