Строки соединения Entity Framework Core 1.0
Мы работаем над различными приложениями ASP.NET Core MVC 1.0. У нас есть 4 уровня для каждого из наших приложений:
- DTO
- Репозиторий (Entity Framework - первый код)
- Служба (бизнес-логика)
- MVC (UI-MVC)
В настоящее время в наших репозиториях, которые обрабатывают все операции с базой данных, мы жестко закодировали строки подключения к базе данных в DbContext следующим образом:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlServer("Data Source=somedatabase.database.windows.net;Initial Catalog=database;Integrated Security=False;User ID=username;Password=password;Connect Timeout=60;Encrypt=True;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False;MultipleActiveResultSets=true");
}
Этот проект находится за пределами проекта MVC как автономный проект ASP.NET Core 1.0. У него также есть пустой файл Program.cs, который, как представляется, требуется для выполнения командных строк кода в базу данных (обновление сетевых сообщений dotnet ef и обновление базы данных dotnet ef).
Причина, по которой у нас есть строка с жестким кодированием в DbConext, заключается в том, что, когда мы используем следующий код, мы получаем ссылку на объект, не установленную в экземпляр для исключения объекта, при выполнении команд dotnet ef.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlServer(ConfigurationManager.ConnectionStrings["StandardDatabase"].ConnectionString);
}
Однако, поскольку у нас есть Program.cs, если мы добавим Debug.WriteLine для строки подключения и запустим проект, она вернет правильную строку соединений, и если мы установим строку подключения в файле appsettings.json в пользовательский интерфейс, пользовательский интерфейс также будет успешно подключен.
ВЫПУСК:
Вышеупомянутый стек - это то, что мы используем для нескольких "Micro Apps", что означает, что у нас есть несколько проектов, которые подключаются к нескольким базам данных. Мы также хотим использовать строки разработки, Staging и Production.
Если мы используем Connection Connection Connection String, все хорошо для ежедневных операций; однако, когда мы хотим использовать код Entity Frameworks в командных строках базы данных, нам нужно зайти в каждый репозиторий, который мы хотим обновить, и изменить DbContext на строку жесткого кодированного соединения, выполнить команды, а затем вернуть их обратно, когда это будет сделано, что становится довольно хлопотным.
ВОПРОС:
Делаем ли мы это неправильно, есть ли предпочтительная практика для создания стека Entity Framework Core 1.0, который позволяет нам не вручную изменять DbContext, а использовать файлы конфигурации по всем направлениям?
Любое направление будет оценено!
Ответы
Ответ 1
EF Core предназначен для настройки посредством инъекции зависимостей. Инъекционная инъекция сохраняет чистоту DbContext и не зависит от деталей реализации среды.
Ваше первоначальное решение жестко-кодирующих строк соединения тесно связано с DbContext, чтобы знать, где находится база данных. Это, очевидно, проблема. Но ваше предлагаемое решение решительно связывает DbContext с информацией о конкретном файле конфигурации. Это тоже проблема.
Чтобы DbContext не зависел от данных о состоянии окружающей среды, создайте конструктор, который принимает параметр DbContextOptions
и вызывает конструктор базового класса.
public class MyContext : DbContext
{
public MyContext(DbContextOptions options) :
base(options)
{
}
}
Сделайте это вместо переопределения OnConfiguring
. Затем инициализируйте его в Startup.cs
вашего хост-приложения. То, что принадлежит знанию файла конфигурации.
public class Startup
{
private IConfigurationRoot _configuration;
public Startup(IHostingEnvironment env)
{
_configuration = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json")
.Build();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IConfigurationRoot>(_configuration);
services.AddDbContext<MyContext>(options => options
.UseSqlServer(_configuration.GetConnectionString("MyContext")));
}
}
Теперь вы можете использовать свой DbContext где угодно.
Ответ 2
ОТВЕТ: Я делал это намного сложнее, чем это было на самом деле. Я последовал за рекомендациями Juunas и добавил следующий код в свой класс DbContext Repository:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
// get the configuration from the app settings
var config = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
// define the database to use
optionsBuilder.UseSqlServer(config.GetConnectionString("StandardDatabase"));
}
Что отлично работает с инструментами командной строки dotnet ef, и поскольку настройка множественного окружения идет с моим MVC-интерфейсом, который придерживается следующего кода по умолчанию в моем startup.cs, отлично работает.
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddJsonFile("project.json", optional: true, reloadOnChange: true);
Ответ 3
IDbContextFactory также может помочь. Инструменты командной строки EF и DI могут использовать этот factory для создания экземпляров вашего DBContext. В службах Time Time (например, Migrations) будут обнаружены реализации этого интерфейса, которые находятся в той же сборке, что и производный контекст.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace MyProject
{
public class BloggingContextFactory : IDbContextFactory<BloggingContext>
{
public BloggingContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlite("Filename=./blog.db");
return new BloggingContext(optionsBuilder.Options);
}
}
}