2016-08-16 2 views
10

Мы работаем с различными приложениями ASP.NET Core MVC 1.0. У нас есть 4-русов к каждому из наших приложений следующим образом:Entity Framework Core 1.0 Строки подключения

  1. DTO
  2. Repository (Entity Framework - Code First)
  3. служба (Business Logic)
  4. 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 migrations и обновление базы данных 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», что означает, у нас есть несколько проектов, которые подключаются к нескольким базам данных. Мы также хотим воспользоваться цепочками соединений Development, Staging and Production.

Если мы используем Connection Connection Connection String, все хорошо для ежедневных операций; однако, когда мы хотим использовать код Entity Frameworks в командных строках базы данных, нам нужно зайти в каждый репозиторий, который мы хотим обновить, и изменить DbContext на строку жесткого кодированного соединения, выполнить команды, а затем вернуть их обратно, когда это будет сделано , что становится довольно хлопотным.

ВОПРОС: ли мы просто делаем это неправильно, есть предпочтительная практика для установки в 1.0 стек Entity Framework Core, которая позволяет нам не следует вручную изменить DbContext но воспользоваться файлами конфигурации поперек доска?

Любое направление будет оценено!

+0

Больше нет MVC6 !!! https://blogs.msdn.microsoft.com/webdev/2016/01/19/asp-net-5-is-dead-introducing-asp-net-core-1-0-and-net-core-1- 0/ – Tseng

+0

Создать заводской метод (или фабричный класс), который управляет соединениями и возвращает Dbcontext –

+2

Почему вы не используете обычную конфигурацию ASP.NET Core вместо использования ConfigurationManager? – juunas

ответ

10

ANSWER: Я делал это намного сложнее, чем на самом деле. Я последовал совету Juunas' и добавил следующий код в моем Repository DbContext Класс:

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 эф инструментов командной строки и до множественная установки среды идет с моим MVC UI придерживаться следующих код по умолчанию в моем 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); 
2

IDbContextFactory также может помочь.Инструменты командной строки EF и DI могут использовать эту фабрику для создания экземпляров вашего DBC-контекста. В службах 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); 
     } 
    } 
} 
13

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 из любого места.

+0

Как получить доступ к общедоступному свойству «Конфигурация» из другого места приложения, например. в контроллере или фильтре? Я бы предпочел сделать его «частным» и доступным для всего, что ему нужно, через контейнер DI: 'services.AddSingleton (Configuration);'. – ProfK

+1

Согласен, @ProfK. Публичную собственность следует превратить в частное поле и зарегистрировать в контейнере. По какой-то причине File New Project создает публичное свойство. Я изменю ответ. –

Смежные вопросы