Jak odczytać parametry połączenia w .NET Core?

109

Chcę odczytać tylko parametry połączenia z pliku konfiguracyjnego iw tym celu dodaj plik o nazwie „appsettings.json” do mojego projektu i dodaj do niego następującą zawartość:

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

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

Na ASP.NET użyłem tego:

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

Teraz, jak mogę odczytać „DefaultConnection” w C # i zapisać go w zmiennej ciągu w .NET Core?

motevalizadeh
źródło

Odpowiedzi:

102

Możesz to zrobić za pomocą metody rozszerzenia GetConnectionString:

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

System.Console.WriteLine(conString);

lub z klasą strukturalną dla DI:

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

Uruchomienie:

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

A potem w kontrolerze domowym:

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

z tym w 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
źródło
9
Configurejest metodą rozszerzającą. Powinien być używany najczęściej w następujący sposób: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Jasne, to prawie to samo, ale myślę, że ludzie nieświadomi zaczną po prostu robić to w „zły” sposób, używając niekomentowanej linii, więc być może najlepiej będzie usunąć tę linię. ;)
James Wilkins
@James Wilkins: Bardzo ważne obawy. Jednak w rzeczywistości wolę tę notację niż używanie jej jako metody rozszerzającej - w ten sposób wiem, gdzie jest wykonywane, i mogę kopiować i wklejać z jednego miejsca do drugiego, bez problemów z powodu braku przestrzeni nazw importu. Jedynym problemem jest to, że MS używa przestrzeni nazw do taksonomii zamiast zapobiegania kolizjom nazw - z tego powodu przestrzenie nazw są zbyt długie. Ponadto, jeśli usuniesz przestrzenie nazw i użyjesz metod rozszerzających, te same osoby zaczną narzekać, że kod się nie kompiluje. Nie każdy używa IDE, więc tak jest lepiej.
Stefan Steiger,
3
@JedatKinports: Nie, tylko wtrysk. Nawet jeśli napiszesz metodę statyczną, nadal będziesz potrzebować konfiguracji. Możesz jednak po prostu odczytać plik JSON / YAML ręcznie. Ale to wyeliminuje nadpisania, takie jak tajemnice użytkownika lub inne (np. Konfiguracja z rejestru).
Stefan Steiger,
1
Pojawia się błąd: „MyClass zawiera definicję„ Configuration ”…”
Robert Smith
3
Do czego odnosi się „this.Configuration” w części dotyczącej parametrów połączenia? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000,
112

Opublikowana odpowiedź jest w porządku, ale nie odpowiadała bezpośrednio na to samo pytanie, które miałem na temat odczytywania parametrów połączenia. Dzięki wielu poszukiwaniom znalazłem nieco prostszy sposób na zrobienie tego.

W Startup.cs

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

W swoim kontrolerze dodaj pole na konfigurację i parametr dla niej w konstruktorze

private readonly IConfiguration configuration;

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

Teraz w kodzie widoku możesz uzyskać do niego dostęp na przykład:

connectionString = configuration.GetConnectionString("DefaultConnection");
Brad Patton
źródło
2
Nie zrobiłbym tego w ten sposób. Jeśli pracujesz bez frameworka encji, lepiej zarejestruj fabrykę połączeń jako singleton, np. Aby używać jej z dapper. W razie potrzeby możesz nadal udostępniać właściwość connectionString, ale założę się, że nie byłoby to konieczne w 99% przypadków.
Stefan Steiger
2
Ale jak uzyskać dostęp do konfiguracji w modelach zamiast kontrolera?
Tanmay
2
Im więcej czytam i próbuję, tym bardziej zdaję sobie sprawę, że uzyskanie parametrów połączenia jest dużym przedsięwzięciem. Po prostu otrzymuję wartości zerowe bez względu na to, co próbuję.
MC9000
7
Tak. Zbyt wielu informatyków tworzy ogromne, wysoko wiszące owoce, by tylko powiedzieć „Hello World”. Nie do wiary. Entropia w najlepszym wydaniu.
JustJohn
2
@JustJohn: Rozumiem twoją skargę, ale prawidłowy projekt można przetestować, a to oznacza, że ​​musisz przekazać zależności w konstruktorze, w przeciwnym razie Twoja aplikacja / framework nie będzie testowana jednostkowo. Jest to również właściwy projekt, ponieważ możesz po prostu zastąpić jeden komponent innym, bez konieczności zmiany całej dużej ilości kodu. Jeśli nie chcesz przekazywać 100 argumentów, możesz również przekazać do klasy System.IServiceProvider, a następnie pobrać tam zależności. Ale druga strona medalu polega na tym, że wiąże się to z dodatkową złożonością.
Stefan Steiger,
18

Zobacz link, aby uzyskać więcej informacji: 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")));
}

EDYCJA: aspnetcore, począwszy od 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1

markokstate
źródło
Dlaczego plik JSON powinien mieć ConnectionStringszamiast ConnectionString? Ponieważ kiedy użyłem ConnectionString, otrzymuję zero.
Vijay,
@Vijay W takim razie spróbuj skorzystać z zalecanej metody;) Zobacz załączony link.
markokstate
1
Ta metoda wydaje się nieaktualna w dniu Microsoft.Extensions.Configuration(3.1.5)
Ju66ernaut
7

Sposób, w jaki znalazłem rozwiązanie tego problemu, polegał na użyciu AddJsonFile w programie budującym podczas uruchamiania (który pozwala mu znaleźć konfigurację przechowywaną w pliku appsettings.json), a następnie użyć tego do ustawienia prywatnej zmiennej _config

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

A potem mogłem ustawić ciąg konfiguracyjny w następujący sposób:

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

To jest w dotnet core 1.1

Alex White
źródło
5
jak mogę uzyskać dostęp do _config w mojej kontrolce?
słoneczny
Dodając go do kontenera DI w ConfigureServices w Startup.cs.
Stefan Steiger,
3

ASP.NET Core ( w moim przypadku 3.1 ) zapewnia nam iniekcje konstruktora do kontrolerów , więc możesz po prostu dodać następujący konstruktor:

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

Oto jak może wyglądać appsettings.json:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}
antonpv
źródło
0

Jest inne podejście. W moim przykładzie widzisz logikę biznesową w klasie repozytorium, której używam z iniekcją zależności w ASP .NET MVC Core 3.1.

I tutaj chcę uzyskać connectiongStringdla tej logiki biznesowej, ponieważ prawdopodobnie inne repozytorium będzie miało w ogóle dostęp do innej bazy danych.

Ten wzorzec umożliwia w tym samym repozytorium logiki biznesowej dostęp do różnych baz danych.

DO#

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"
  }
}
Deweloper
źródło
-1

Mam bibliotekę dostępu do danych, która działa zarówno z .NET core i .NET Framework.

sztuczka polegała na zachowaniu parametrów połączenia w pliku xml o nazwie „app.config” (również w przypadku projektów internetowych) i oznaczeniu go jako „kopiuj do katalogu wyjściowego”,

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

ConfigurationManager.ConnectionStrings - odczyta parametry połączenia.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
shaig
źródło
Jeśli korzystasz z platformy .NET Core, najlepiej jest przyjąć jego wzorzec konfiguracji zamiast tworzenia butów we wzorcu .NET Framework.
Simmetric