Как настроить DbContext при создании миграций в Entity Framework Core?
есть ли способ, которым инъекция зависимостей может быть настроена / загружена при использовании команд миграции Entity Framework?
ядро Entity Framework поддерживает инъекцию зависимостей для DbContext
подклассы. Этот механизм включает в себя возможность настройки доступа к данным за пределами DbContext
.
например, следующая настройка EF для сохранения на SQL server с помощью строки подключения, полученной из config.json
ServiceCollection services = ...
var configuration = new Configuration().AddJsonFile( "config.json" );
services.AddEntityFramework( configuration )
.AddSqlServer()
.AddDbContext<BillingDbContext>( config => config.UseSqlServer() );
, команды миграции не знают, как выполнить этот код, поэтому Add-Migration
произойдет сбой из-за отсутствия поставщика или отсутствия строки подключения.
миграции могут быть сделаны для работы путем переопределения OnConfiguring
внутри DbContext
подкласс для указания поставщика и строки конфигурации, но это мешает, когда требуется другая конфигурация в другом месте. В конечном итоге сохранение моих команд миграции и моего кода становится нежелательно сложным.
Примечание: Мой DbContext
живет в другой сборке, чем точка входа, которая ее использует, и мое решение имеет несколько проектов запуска.
5 ответов
As @bricelam commented эта функция еще не существует в Entity Framework 7. Эта отсутствующая функциональность отслеживается GitHub issue aspnet / EntityFramework#639
в то же время, более легким обходным путем, который я нашел, было использование глобального состояния, а не хлопот с подклассами. Обычно это не мой первый выбор дизайна, но сейчас он работает хорошо.
В MyDbContext:
public static bool isMigration = true;
protected override void OnConfiguring( DbContextOptionsBuilder optionsBuilder )
{
// TODO: This is messy, but needed for migrations.
// See https://github.com/aspnet/EntityFramework/issues/639
if ( isMigration )
{
optionsBuilder.UseSqlServer( "<Your Connection String Here>" );
}
}
In Startup.ConfigureServices()
.
public IServiceProvider ConfigureServices( IServiceCollection services )
{
MyContext.isMigration = false;
var configuration = new Configuration().AddJsonFile( "config.json" );
services.AddEntityFramework( configuration )
.AddSqlServer()
.AddDbContext<MyDbContext>( config => config.UseSqlServer() );
// ...
}
(код конфигурации фактически живет в модуле Autofac в моем случае.)
используя IDbContextFactory<TContext>
реализуйте этот интерфейс, чтобы включить службы времени разработки для типов контекста, которые не имеют открытого конструктора по умолчанию. Службы времени разработки автоматически обнаружат реализации этого интерфейса, которые находятся в той же сборке, что и производный контекст.
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace MyProject
{
public class BloggingContextFactory : IDbContextFactory<BloggingContext>
{
public BloggingContext Create()
{
var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
optionsBuilder.UseSqlServer("connection_string");
return new BloggingContext(optionsBuilder.Options);
}
}
}
подробнее : https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext
Если вы не довольны жестко закодированная строка подключения, взгляните на этой статьи.
Я знаю, что это старый вопрос, но я использую метод onConfiguring, и у меня нет этой проблемы
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(Startup.Configuration.Get("Data:DefaultConnection:ConnectionString"));
}
Я просто прошу экземпляр и запускаю миграции в моем запуске.cs файл
public void ConfigureServices(IServiceCollection services)
{
// ASPNet Core Identity
services.AddDbContext<RRIdentityDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("RRIdentityConnectionString")));
}
а затем в Configure:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
var rrIdentityContext = app.ApplicationServices.GetService<RRIdentityDbContext>();
rrIdentityContext.Database.Migrate();
}
Примечание: Для базы данных нет "EnsureCreated". Migrate должен создать его, если он не существует, хотя как он должен выяснить разрешения, я не знаю - поэтому я создал пустую базу данных.
объединить ответы выше это работает для меня
private readonly bool isMigration = false;
public MyContext()
{
isMigration = true;
}
public MyContext(DbContextOptions<MyContext> options) : base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (isMigration)
{
optionsBuilder.UseSqlServer("CONNECTION_STRING");
}
}