Создание DbContext во время разработкиDesign-time DbContext Creation

Для некоторых команд EF Core инструментов (например, для команд миграции ) DbContext во время разработки необходимо создать производный экземпляр, чтобы получить сведения о типах сущностей приложения и их сопоставлении со схемой базы данных.Some of the EF Core Tools commands (for example, the Migrations commands) require a derived DbContext instance to be created at design time in order to gather details about the application's entity types and how they map to a database schema. В большинстве случаев желательно, DbContext чтобы созданный таким образом объект был настроен аналогично тому, как он будет настроен во время выполнения.In most cases, it is desirable that the DbContext thereby created is configured in a similar way to how it would be configured at run time.

Существует несколько способов, с помощью которых средства пытаются создать DbContext :There are various ways the tools try to create the DbContext:

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

Если запускаемый проект использует ASP.NET Core веб-узел или универсальный узел .NET Core, средства пытаются получить объект DbContext от поставщика услуг приложения.If your startup project uses the ASP.NET Core Web Host or .NET Core Generic Host, the tools try to obtain the DbContext object from the application's service provider.

Сначала средства пытаются получить поставщик услуг путем вызова Program.CreateHostBuilder() , вызова Build() и доступа к Services свойству.The tools first try to obtain the service provider by invoking Program.CreateHostBuilder(), calling Build(), then accessing the Services property.

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)
    {
    }
}

Примечание

При создании нового ASP.NET Core приложения этот обработчик включается по умолчанию.When you create a new ASP.NET Core application, this hook is included by default.

DbContextСам по себе и все зависимости в конструкторе должны быть зарегистрированы в качестве служб в поставщике услуг приложения.The DbContext itself and any dependencies in its constructor need to be registered as services in the application's service provider. Это можно легко сделать, используя конструктор DbContext , который принимает экземпляр DbContextOptions<TContext> в качестве аргумента и использует AddDbContext<TContext> метод.This can be easily achieved by having a constructor on the DbContext that takes an instance of DbContextOptions<TContext> as an argument and using the AddDbContext<TContext> method.

Использование конструктора без параметровUsing a constructor with no parameters

Если DbContext невозможно получить от поставщика службы приложений, средства ищут производный DbContext тип внутри проекта.If the DbContext can't be obtained from the application service provider, the tools look for the derived DbContext type inside the project. Затем они пытаются создать экземпляр с помощью конструктора без параметров.Then they try to create an instance using a constructor with no parameters. Это может быть конструктор по умолчанию, если DbContext настроен с помощью OnConfiguring метода.This can be the default constructor if the DbContext is configured using the OnConfiguring method.

Из фабрики времени разработкиFrom a design-time factory

Вы также можете сообщить средствам, как создать DbContext, реализовав Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> интерфейс: Если класс, реализующий этот интерфейс, находится в том же проекте, что и производный, DbContext или в проекте запуска приложения, средства обходят другие способы создания DbContext и используют вместо этого фабрику времени разработки.You can also tell the tools how to create your DbContext by implementing the Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> interface: If a class implementing this interface is found in either the same project as the derived DbContext or in the application's startup project, the tools bypass the other ways of creating the DbContext and use the design-time factory instead.

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);
    }
}

Примечание

До Ефкоре 5,0 args параметр был неиспользован (см. эту ошибку).Prior to EFCore 5.0 the args parameter was unused (see this issue). Это исправлено в Ефкоре 5,0, а все дополнительные аргументы времени разработки передаются в приложение через этот параметр.This is fixed in EFCore 5.0 and any additional design-time arguments are passed into the application through that parameter.

Фабрика времени разработки может быть особенно полезной, если необходимо настроить DbContext разное время разработки, чем во время выполнения, если DbContext конструктор принимает дополнительные параметры, не зарегистрированные на сайте di, если вы не используете функцию Onon или по какой-либо причине не хотите использовать CreateHostBuilder метод в классе ASP.NET Core приложения Main .A design-time factory can be especially useful if you need to configure the DbContext differently for design time than at run time, if the DbContext constructor takes additional parameters are not registered in DI, if you are not using DI at all, or if for some reason you prefer not to have a CreateHostBuilder method in your ASP.NET Core application's Main class.

ArgsArgs

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

Начиная с EF Core 5,0, можно указать следующие аргументы в средствах:Starting in EF Core 5.0, you can specify these arguments from the tools:

dotnet ef database update -- --environment Production

--Токен направляет dotnet ef все, что следует за аргументом, и не пытается проанализировать их как параметры.The -- token directs dotnet ef to treat everything that follows as an argument and not try to parse them as options. Все дополнительные аргументы, не используемые, dotnet ef пересылаются в приложение.Any extra arguments not used by dotnet ef are forwarded to the app.