Как читать строку подключения в .NET Core?

110

Я хочу прочитать только строку подключения из файла конфигурации и для этого добавить в свой проект файл с именем «appsettings.json» и добавить в него это содержимое:

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

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

В ASP.NET я использовал это:

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

Как теперь я могу прочитать «DefaultConnection» в C # и сохранить его в строковой переменной в .NET Core?

Мотевализаде
источник

Ответы:

103

Вы можете сделать это с помощью метода расширения GetConnectionString:

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

System.Console.WriteLine(conString);

или со структурированным классом для DI:

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

Запускать:

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

А потом в хоум-контроллере:

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

с этим в appsettings.json:

"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-WebApplica71d622;Trusted_Connection=True;MultipleActiveResultSets=true"
},

"Smtp": {
    "Server": "0.0.0.1",
    "User": "user@company.com",
    "Pass": "123456789",
    "Port": "25"
  }
Стефан Штайгер
источник
9
Configureэто метод расширения. Чаще всего его следует использовать так: services.Configure<SmtpConfig>(Configuration.GetSection("Smtp"));Конечно, это почти то же самое, но я думаю, что люди, не знающие об этом, просто начнут делать это «неправильным» способом, используя строку без комментариев, поэтому, возможно, лучше всего удалить строку. ;)
Джеймс Уилкинс
@ Джеймс Уилкинс: Очень серьезные опасения. Однако на самом деле я предпочитаю использовать эту нотацию в качестве метода расширения - таким образом я знаю, что и где делается, и могу копировать и вставлять из одного места в другое без проблем из-за отсутствия пространств имен импорта. Единственная проблема заключается в том, что MS использует пространства имен для таксономии вместо предотвращения конфликтов имен - из-за этого пространства имен слишком длинные. Кроме того, если вы удалите пространства имен и используете методы расширения, те же люди начнут жаловаться на то, что код не компилируется. Не все используют IDE, так что так лучше.
Stefan Steiger
3
@JedatKinports: Нет, только инъекция. Даже если вы напишете статический метод, вам все равно понадобится конфигурация. Однако вы можете просто прочитать файл JSON / YAML вручную. Но это устранит перезаписи, такие как пользовательские секреты или другие (например, конфигурация из реестра).
Стефан Штайгер
1
Я получаю сообщение об ошибке: «MyClass действительно содержит определение« Конфигурация »...»
Роберт Смит
3
Что означает this.Configuration в части строки подключения? GetConnectionString (this.Configuration, "DefaultConnection")
MC9000,
112

Опубликованный ответ хорош, но не ответил напрямую на тот же вопрос, который у меня был о чтении в строке подключения. Путем долгих поисков я нашел более простой способ сделать это.

В Startup.cs

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

В вашем контроллере добавьте поле для конфигурации и параметр для него в конструкторе

private readonly IConfiguration configuration;

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

Теперь позже в вашем коде представления вы можете получить к нему доступ, например:

connectionString = configuration.GetConnectionString("DefaultConnection");
Брэд Паттон
источник
2
Не стал бы так поступать. Если вы работаете без Entity Framework, вам лучше зарегистрировать фабрику соединений как singleton, например, для использования с dapper. Затем вы все равно можете предоставить свойство connectionString, если вам нужно, но я уверен, что в 99% случаев это не понадобится.
Stefan Steiger
2
Но как получить доступ к конфигурации в моделях вместо контроллера?
Tanmay
2
Чем больше я читаю и пробую что-то, тем больше понимаю, что получение строки подключения - серьезная задача. Я просто получаю нули, что бы я ни пытался.
MC9000 01
7
Да. Слишком много компьютерных ученых создают огромные высоко висящие фрукты, чтобы просто сказать «Привет, мир». Невероятно. Энтропия в лучшем случае.
JustJohn
2
@JustJohn: Я понимаю вашу жалобу, но правильный дизайн можно протестировать, а это означает, что вам нужно передать зависимости в конструкторе, иначе ваше приложение / фреймворк нельзя тестировать по модулю. Это тоже правильный дизайн, так как вы можете просто заменить один компонент другим без необходимости менять много кода. Если вы не хотите передавать 100 аргументов, вы также можете передать System.IServiceProvider в класс, после чего вы можете получить оттуда зависимости. Но другая сторона медали в том, что это связано с дополнительной сложностью.
Стефан Штайгер
18

См. Ссылку для получения дополнительной информации: 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")));
}

РЕДАКТИРОВАТЬ: aspnetcore, начиная с 3.1: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-3.1

Markokstate
источник
Почему должен быть файл JSON ConnectionStringsвместо ConnectionString? Потому что когда я использовал ConnectionString, то мы получаем null.
Vijay
@Vijay Тогда попробуйте использовать предписанный метод;) См. Прикрепленную ссылку.
markokstate
1
Этот метод кажется устаревшим с Microsoft.Extensions.Configuration(3.1.5)
Ju66ernaut
7

Я нашел способ решить эту проблему, используя AddJsonFile в построителе при запуске (что позволяет ему найти конфигурацию, хранящуюся в файле appsettings.json), а затем использовать это для установки частной переменной _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();
    }

И затем я мог бы установить строку конфигурации следующим образом:

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

Это на ядре dotnet 1.1

Алекс Уайт
источник
5
как я могу получить доступ к _config в моем управлении?
солнечно,
Добавив его в контейнер DI в ConfigureServices в Startup.cs.
Стефан Штайгер
3

ASP.NET Core ( в моем случае 3.1 ) предоставляет нам инъекции конструктора в контроллеры , поэтому вы можете просто добавить следующий конструктор:

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

Вот как может выглядеть appsettings.json:

{
    "ConnectionStrings": {
        "Default": "YOUR_CONNECTION_STRING"
        }
}
antonpv
источник
0

Есть другой подход. В моем примере вы видите некоторую бизнес-логику в классе репозитория, который я использую с внедрением зависимостей в ASP .NET MVC Core 3.1.

И здесь я хочу получить connectiongStringэту бизнес-логику, потому что, вероятно, другой репозиторий вообще будет иметь доступ к другой базе данных.

Этот шаблон позволяет вам в одном репозитории бизнес-логики иметь доступ к разным базам данных.

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"
  }
}
Разработчик
источник
0

В версии 3.1 уже определен раздел для "ConnectionStrings".

System.Configuration.ConnnectionStringSettings

Определите :

  "ConnectionStrings": {
    "ConnectionString": "..."
  }

Зарегистрироваться :

public void ConfigureServices(IServiceCollection services)
{
     services.Configure<ConnectionStringSettings>(Configuration.GetSection("ConnectionStrings"));
}

Ввести :

public class ObjectModelContext : DbContext, IObjectModelContext
{

     private readonly ConnectionStringSettings ConnectionStringSettings;

    ...

     public ObjectModelContext(DbContextOptions<ObjectModelContext> options, IOptions<ConnectionStringSettings> setting) : base(options)
    {
          ConnectionStringSettings = setting.Value;
    }

    ...
}

Использование :

   public static void ConfigureContext(DbContextOptionsBuilder optionsBuilder, ConnectionStringSettings connectionStringSettings)
    {
        if (optionsBuilder.IsConfigured == false)
        {
            optionsBuilder.UseLazyLoadingProxies()
                          .UseSqlServer(connectionStringSettings.ConnectionString);
        }
    }
Крейг
источник
-1

У меня есть библиотека доступа к данным, которая работает как с ядром .net, так и с .net framework.

уловка заключалась в том, что в основных проектах .net строки подключения сохранялись в XML-файле с именем «app.config» (также для веб-проектов) и помечались как «копировать в выходной каталог»,

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

ConfigurationManager.ConnectionStrings - прочитает строку подключения.

    var conn1 = ConfigurationManager.ConnectionStrings["conn1"].ConnectionString;
Shaig
источник
Если вы используете .NET Core, лучше использовать его шаблон конфигурации, а не использовать шаблон .NET Framework.
Simmetric,