Получите ConnectionString из appsettings.json вместо жесткого кодирования в приложении .NET Core 2.0
У меня есть следующий класс в приложении NET Core2.0.
// 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);
}
}
Это требуется в Core 2.0 с миграцией, когда база данных не существует и должна быть создана при запуске базы данных обновлений.
Невозможно создать миграцию после обновления до ASP.NET Core 2.0
Я бы не хотел иметь ConnectionString в 2-х местах (здесь и в appsettings.json), но только в .json
поэтому я попытался заменить
"Server=localhost;Database=DbName;Trusted_Connection=True;MultipleActiveResultSets=true"
с
ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString
но он не работает, я получаю нулевое значение.
ОБНОВЛЕНИЕ 1:
Просто отметим, что добавление явно .json не требуется в Core 2, поэтому проблема не в файле.
https://andrewlock.net/exploring-program-and-startup-in-asp-net-core-2-preview1-2/
ОБНОВЛЕНИЕ 2:
Также я уже использую Configuration для отправки ConnectionString из .json в контекст:
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")));
}
}
Но я не могу использовать это для ToDoContextFactory, потому что у него нет конфигурации, а ToDoContextFactory используется для миграции, поэтому приложение не работает вообще.
РЕШЕНИЕ:
Основываясь на ответе от @JRB, я сделал это так:
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);
}
Ответы
Ответ 1
ШАГ 1: Включите в OnConfiguring()
следующее:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
.AddJsonFile("appsettings.json")
.Build();
optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
}
ШАГ 2: Создайте appsettings.json:
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"
}
}
ШАГ 3: Жесткая копия appsettings.json в правильный каталог
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.
Предположение: вы уже включили пакет Microsoft.Extensions.Configuration.Json(получите его от Nuget) в свой проект.
Ответ 2
В ASPNET Core вы делаете это в Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<BloggingContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("BloggingDatabase")));
}
где ваше соединение определено в appsettings.json
{
"ConnectionStrings": {
"BloggingDatabase": "..."
},
}
Пример из документов MS
Ответ 3
Как пропустить его как dp-инъекцию в этот класс?
в ConfigureServices:
services.Configure<MyOptions>(Configuration);
создать класс для хранения строк json:
public class MyOptions
{
public MyOptions()
{
}
public string Option1 { get; set; }
public string Option2 { get; set; }
}
Добавьте строки в json файл:
"option1": "somestring",
"option2": "someothersecretstring"
В классах, которым нужны эти строки, передайте в качестве конструктора:
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
}
}
Ответ 4
Фактически используется шаблон по умолчанию, который можно использовать для достижения этого результата без необходимости выполнять IDesignTimeDbContextFactory
и выполнять любое копирование файла конфигурации.
Подробно в этот документ, в котором также обсуждаются другие способы, с помощью которых инфраструктура будет пытаться создать экземпляр DbContext
при проектировании время.
В частности, вы используете новый крючок, в данном случае статический метод формы public static IWebHost BuildWebHost(string[] args)
. Документация подразумевает в противном случае, но этот метод может жить в любом классе, где находится ваша точка входа (см. Src). Реализация этого является частью руководства в документе 1.x to 2.x, и то, что не совсем очевидно, смотрит на код, заключается в том, что вызов WebHost.CreateDefaultBuilder(args)
- это, помимо прочего, подключение вашей конфигурации в шаблоне по умолчанию, с которого начинаются новые проекты. Это все, что вам нужно, чтобы настроить конфигурацию для служб времени разработки, таких как миграции.
Здесь более подробно о том, что происходит в глубине:
При добавлении миграции, когда структура пытается создать ваш DbContext
, он сначала добавляет любые реализации IDesignTimeDbContextFactory
, которые он находит набор методов factory, которые можно использовать для создания вашего контекста, затем он получает ваши настроенные службы через статический крючок, обсуждаемый ранее, и выглядит для любых типов контекстов, зарегистрированных с помощью DbContextOptions
(который происходит в вашем Startup.ConfigureServices
при использовании AddDbContext
или AddDbContextPool
) и добавляет эти заводы. Наконец, просматривает через сборку для любых DbContext
производных классов и создает метод factory, который просто вызывает Activator.CreateInstance
как окончательный приветствую Мэри.
Порядок приоритета, который использует каркас, такой же, как и выше. Таким образом, если вы выполнили IDesignTimeDbContextFactory
, он переопределит упомянутый выше крючок. Однако для большинства распространенных сценариев вам не понадобится IDesignTimeDbContextFactory
.
Ответ 5
Я понимаю, что это было помечено как ответ, но я столкнулся с небольшой проблемой, когда работал над проектом, в котором мой уровень доступа к базовым данным EF в проекте .DLL отделен от остальной части моего проекта, API, Auth и Сеть и в основном понравятся мои другие проекты, чтобы ссылаться на этот проект данных. И я не хочу заходить в проект Data, чтобы каждый раз менять строки подключения.
ШАГ 1. Включите это в метод OnConfiguring.
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"));
}
ПРИМЕЧАНИЕ..SetBasePath(Path.Combine(Directory.GetCurrentDirectory())) Это сведет на нет или сделает недействительной необходимость копирования файла в каталог, поскольку ASP.NET CORE достаточно умен, чтобы выбрать правильный файл. Также указанная среда выберет правильный файл при сборке для выпуска или производства, при условии, что выбран файл среды Prod.
ШАГ 2: Создайте appsettings.json
{
"ConnectionStrings": {
"DefaultConnection": "Server=YOURSERVERNAME; Database=YOURDATABASENAME; Trusted_Connection=True; MultipleActiveResultSets=true"
}
}
ПОЖАЛУЙСТА: Ссылка: Microsoft.Extensions.Configuration
Ответ 6
Не хватает нескольких вещей, как из приведенных выше решений, так и из документации Microsoft. Если вы перейдете по ссылке на репозиторий GitHub, ссылка на которую приведена в документации выше, вы найдете реальное решение.
Я думаю, что путаница заключается в том, что шаблоны по умолчанию, которые используют многие люди, не содержат конструктор по умолчанию для автозагрузки, поэтому люди не обязательно знают, откуда приходит внедренная конфигурация.
Итак, в Startup.cs добавьте:
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
а затем в методе ConfigureServices добавьте то, что сказали другие люди...
services.AddDbContext<ChromeContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DatabaseConnection")));
вы также должны убедиться, что у вас создан файл appsettings.json и есть раздел строк подключения, аналогичный этому
{
"ConnectionStrings": {
"DatabaseConnection": "Server=MyServer;Database=MyDatabase;Persist Security Info=True;User ID=SA;Password=PASSWORD;MultipleActiveResultSets=True;"
}
}
Конечно, вам придется изменить это, чтобы отразить вашу конфигурацию.
Вещи, чтобы иметь в виду. Это было протестировано с использованием Entity Framework Core 3 в проекте .Net Standard 2.1.
Мне нужно было добавить пакеты nuget для:
Microsoft.EntityFrameworkCore 3.0.0
Microsoft.EntityFrameworkCore.SqlServer 3.0.0, потому что то, что я использую, и то, что требуется для получения доступа к UseSqlServer.
Ответ 7
Вы также можете сделать это в ASP.NET Core 2, определив строку подключения в файле appSettings.json
. Затем в Startup.cs
вы указываете, какую строку подключения использовать.
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));
Ответ 8
-
Добавьте следующий код в файл 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
}
-
Используйте свойство GlobalProperties.DBConnection
в классе Context
.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer(GlobalProperties.DBConnection);
}
}
Ответ 9
Я не знаю, что вы знаете, но вы можете использовать класс обратного вызова, создать hostbuilder и установить для конфигурации статическое свойство.
Для ядра ASP 2.2:
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using System;
namespace Project
{
sealed class Program
{
#region Variables
/// <summary>
/// Last loaded configuration
/// </summary>
private static IConfiguration _Configuration;
#endregion
#region Properties
/// <summary>
/// Default application configuration
/// </summary>
internal static IConfiguration Configuration
{
get
{
// None configuration yet?
if (Program._Configuration == null)
{
// Create the builder using a callback class
IWebHostBuilder builder = WebHost.CreateDefaultBuilder().UseStartup<CallBackConfiguration>();
// Build everything but do not initialize it
builder.Build();
}
// Current configuration
return Program._Configuration;
}
// Update configuration
set => Program._Configuration = value;
}
#endregion
#region Public
/// <summary>
/// Start the webapp
/// </summary>
public static void Main(string[] args)
{
// Create the builder using the default Startup class
IWebHostBuilder builder = WebHost.CreateDefaultBuilder(args).UseStartup<Startup>();
// Build everything and run it
using (IWebHost host = builder.Build())
host.Run();
}
#endregion
#region CallBackConfiguration
/// <summary>
/// Aux class to callback configuration
/// </summary>
private class CallBackConfiguration
{
/// <summary>
/// Callback with configuration
/// </summary>
public CallBackConfiguration(IConfiguration configuration)
{
// Update the last configuration
Program.Configuration = configuration;
}
/// <summary>
/// Do nothing, just for compatibility
/// </summary>
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//
}
}
#endregion
}
}
Итак, теперь вы просто используете статическую Program.Configuration в любом другом классе, который вам нужен.