Как настроить 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");
    }
}