Поделиться через


Создание DbContext на этапе разработки

Некоторые команды EF Core Tools (например, команды миграции) требуют, чтобы производный экземпляр DbContext был создан во время проектирования для сбора сведений о типах сущностей приложения и их сопоставления с схемой базы данных. В большинстве случаев желательно, чтобы DbContext было настроено аналогично тому, как оно настроено во время выполнения.

Есть различные способы, которыми инструменты пытаются создать DbContext.

Из служб приложений

Если в проекте запуска используется веб-узел ASP.NET Core или универсальный узел .NET Core, средства пытаются получить объект DbContext от поставщика услуг приложения.

Средства сначала пытаются получить поставщика услуг путем вызова Program.CreateHostBuilder(), выполнения Build(), а затем доступа к свойству Services.

public class Program
{
    public static void Main(string[] args)
        => CreateHostBuilder(args).Build().Run();

    // EF Core uses this method at design time to access the DbContext
    public static IHostBuilder CreateHostBuilder(string[] args)
        => Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(
                webBuilder => webBuilder.UseStartup<Startup>());
}

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
        => services.AddDbContext<ApplicationDbContext>();

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
    }
}

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    {
    }
}

Note

При создании нового приложения ASP.NET Core этот механизм включается по умолчанию.

Само DbContext и все зависимости в конструкторе должны быть зарегистрированы в качестве служб в поставщике услуг приложения. Это можно легко достичь, имея конструктор у , который принимает экземпляр в качестве аргумента и с использованием метода .

Использование конструктора без параметров

Если dbContext не удается получить от поставщика службы приложений, средства ищут производный DbContext тип внутри проекта. Затем они пытаются создать экземпляр с помощью конструктора без параметров. Это может быть конструктор по умолчанию, если DbContext он настроен с помощью OnConfiguring метода.

Из фабрики проектирования

Вы также можете указать инструментам, как создать ваш DbContext, реализуя Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> интерфейс: Если класс, реализующий этот интерфейс, найден в том же проекте, что и производный DbContext, или в проекте запуска приложения, средства обходят другие способы создания DbContext и используют фабрику на стадии разработки.

public class BloggingContextFactory : IDesignTimeDbContextFactory<BloggingContext>
{
    public BloggingContext CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<BloggingContext>();
        optionsBuilder.UseSqlite("Data Source=blog.db");

        return new BloggingContext(optionsBuilder.Options);
    }
}

Фабрика для времени разработки может быть особенно полезной, если необходимо настроить DbContext иначе для времени разработки, чем во время выполнения, если конструктор DbContext принимает дополнительные параметры, которые не зарегистрированы в DI, если вы вообще не используете DI, или если по какой-то причине вы предпочитаете не иметь метод CreateHostBuilder в классе приложения ASP.NET Core Main.

Args

Оба IDesignTimeDbContextFactory<TContext>.CreateDbContext и Program.CreateHostBuilder принимают аргументы командной строки.

Эти аргументы можно указать с помощью инструментов.

dotnet ef database update -- --environment Production

Маркер -- направляет dotnet ef обрабатывать всё следующее как аргумент и не пытаться анализировать их как параметры. Все дополнительные аргументы, не используемые dotnet ef приложением, перенаправляются в приложение.