Udostępnij za pośrednictwem


Tworzenie klasy DbContext w czasie projektowania

Niektóre polecenia narzędzi EF Core Tools (na przykład polecenia Migracje ) wymagają utworzenia wystąpienia pochodnego DbContext w czasie projektowania w celu zebrania szczegółów dotyczących typów jednostek aplikacji i sposobu mapowania ich na schemat bazy danych. W większości przypadków pożądane jest skonfigurowanie utworzonego DbContext obiektu w podobny sposób do konfiguracji w czasie wykonywania.

Istnieją różne sposoby, w jaki narzędzia próbują utworzyć element DbContext:

Z usług aplikacji

Jeśli projekt startowy używa hosta internetowego platformy ASP.NET Core lub hosta ogólnego platformy .NET Core, narzędzia próbują uzyskać obiekt DbContext od dostawcy usług aplikacji.

Narzędzia najpierw próbują uzyskać dostawcę usług, wywołując Program.CreateHostBuilder()metodę , wywołując Build(), a następnie uzyskując Services dostęp do właściwości.

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

Uwaga

Podczas tworzenia nowej aplikacji ASP.NET Core ten punkt zaczepienia jest domyślnie dołączany.

Samo DbContext i wszelkie zależności w konstruktorze muszą być zarejestrowane jako usługi u dostawcy usług aplikacji. Można to łatwo osiągnąć, używając konstruktora w DbContext obiekcie , który przyjmuje wystąpienie DbContextOptions<TContext> jako argument i przy użyciu AddDbContext<TContext> metody .

Używanie konstruktora bez parametrów

Jeśli nie można uzyskać obiektu DbContext od dostawcy usług aplikacji, narzędzia szukają typu pochodnego DbContext w projekcie. Następnie próbują utworzyć wystąpienie przy użyciu konstruktora bez parametrów. Może to być domyślny konstruktor, jeśli DbContext jest skonfigurowany przy użyciu OnConfiguring metody .

Z fabryki czasu projektowania

Możesz również powiedzieć narzędziom, jak utworzyć interfejs DbContext, implementując Microsoft.EntityFrameworkCore.Design.IDesignTimeDbContextFactory<TContext> interfejs: Jeśli klasa implementjąca ten interfejs zostanie znaleziona w tym samym projekcie co pochodny DbContext lub w projekcie startowym aplikacji, narzędzia pomijają inne sposoby tworzenia obiektu DbContext i zamiast tego używają fabryki czasu projektowania.

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

Fabryka czasu projektowania może być szczególnie przydatna, jeśli trzeba skonfigurować DbContext inaczej czas projektowania niż w czasie wykonywania, jeśli konstruktor przyjmuje dodatkowe parametry nie są zarejestrowane w di, jeśli DbContext w ogóle nie używasz di, lub jeśli z jakiegoś powodu nie chcesz mieć CreateHostBuilder metody w klasie aplikacji ASP.NET Core Main .

Args

Zarówno IDesignTimeDbContextFactory<TContext>.CreateDbContext , jak i Program.CreateHostBuilder akceptują argumenty wiersza polecenia.

Te argumenty można określić za pomocą narzędzi:

dotnet ef database update -- --environment Production

Token -- kieruje do traktowania wszystkiego, co następuje dotnet ef jako argument i nie próbuje przeanalizować ich jako opcji. Wszelkie dodatkowe argumenty, które nie są używane przez dotnet ef usługę, są przekazywane do aplikacji.