6

Czy istnieje sposób, w jaki zastrzyk zależności można skonfigurować/załadować podczas używania poleceń migracji Entity Framework?Jak skonfigurować DbContext podczas tworzenia migracji w Entity Framework Core?

Entity Framework Core obsługuje wtrysk zależności dla podklas DbContext. Mechanizm ten obejmuje umożliwienie konfiguracji dostępu do danych poza numerem DbContext.

Na przykład, następujący by skonfigurować EF utrzymują się do serwera SQL przy użyciu ciąg połączenia pobierane z config.json

ServiceCollection services = ... 

var configuration = new Configuration().AddJsonFile("config.json"); 
services.AddEntityFramework(configuration) 
    .AddSqlServer() 
    .AddDbContext<BillingDbContext>(config => config.UseSqlServer()); 

Jednakże, polecenia migracje nie wiem, aby wykonać ten kod tak Add-Migration zawiedzie z powodu braku dostawcy lub brak ciągu połączenia.

Migracja może być wykonana poprzez przesłonięcie OnConfiguring w podklasie DbContext w celu określenia dostawcy i łańcucha konfiguracji, ale to przeszkadza, gdy inna konfiguracja jest pożądana gdzie indziej. Ostatecznie utrzymanie moich poleceń migracyjnych i mojego kodu staje się niepożądanie skomplikowane.

Uwaga: Moje DbContext mieszka w innym zespole niż punkt wejścia, który go używa, a moje rozwiązanie ma wiele projektów rozruchowych.

+0

Wyobrażenie tego jest częścią problemu [# 639] (https://github.com/aspnet/EntityFramework/issues/639). W ASP.NET 5 nazwiemy 'Startup.ConfigureServices()'. Czy twoim zdaniem byłoby dobrze zastosować tę samą konwencję dla projektów spoza programu. – bricelam

+0

@bricelam Teraz, gdy zrobiłem trochę rozwoju w ASP.NET 5 (korzystałem z EF7 w tradycyjnej aplikacji .NET), mogę powiedzieć, że standaryzacja wokół klasy "Startup" brzmi dla mnie dobrze. – vossad01

+0

Pchnąłem to w [aspnet/Hosting # 286] (https://github.com/aspnet/Hosting/issues/286), ale zaginąłem. Decyzja dotyczyła różnych ładowarek DbContext dla różnych typów aplikacji. Zobacz [aspnet/EntityFramework # 2357] (https://github.com/aspnet/EntityFramework/issues/2357). – bricelam

Odpowiedz

3

Jak @bricelam skomentował tej funkcji jeszcze nie istnieje w Entity Framework 7. Ta funkcjonalność jest brakuje śledzone przez GitHub wydanie aspnet/EntityFramework#639

W międzyczasie łatwiejsze obejście okazało się wykorzystanie stanu globalnego, a nie kłopotów z podklasy. Nie jest to zazwyczaj mój pierwszy projekt, ale na razie działa dobrze.

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

W 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()); 
    // ... 
} 

(Kod konfiguracji faktycznie mieszka w module Autofac w moim przypadku).

+0

Możesz sprawdzić właściwość OptionBuilder.IsConfigured zamiast flagi isMigration. –

0

wiem, że jest to stare pytanie, ale używam metody onConfiguring i nie mam tego problemu

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 
{ 
    optionsBuilder.UseSqlServer(Startup.Configuration.Get("Data:DefaultConnection:ConnectionString")); 
} 
+1

Dzięki Pedro, chyba że coś się zmieniło, to nie działa w mojej sytuacji. Klasa 'Startup', której używa moja aplikacja, nie może się odwoływać do podklasy' DbContext', ponieważ znajdują się w różnych złożeniach. Wykonanie tej konfiguracji tutaj iw "Uruchomieniu" nie jest kompatybilne. – vossad01

0

po prostu poprosić o przykład i uruchomić migracje w moich Startup.cs złożyć

public void ConfigureServices(IServiceCollection services) 
    { 
     // ASPNet Core Identity 
     services.AddDbContext<RRIdentityDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("RRIdentityConnectionString"))); 

    } 

A potem w Konfiguracji:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     var rrIdentityContext = app.ApplicationServices.GetService<RRIdentityDbContext>(); 
     rrIdentityContext.Database.Migrate(); 
    } 

Uwaga: Nie ma opcji "Upewnij się" dla bazy danych. Migrate ma go utworzyć, jeśli nie istnieje, ale jak to zrobić, aby dowiedzieć się uprawnień, których nie znam - dlatego utworzyłem pustą bazę danych.

0

Aby połączyć odpowiedź powyżej działa to dla mnie

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

Korzystanie IDbContextFactory<TContext>

Wdrożenie tego interfejsu w celu umożliwienia usługi czasu projektowania dla typów kontekstowych, które nie mają domyślnego konstruktora publicznego. Usługi czasu projektowania automatycznie wykrywają implementacje tego interfejsu, które znajdują się w tym samym zespole, co kontekst pochodny.

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

więcej info: https://docs.microsoft.com/en-us/ef/core/miscellaneous/configuring-dbcontext

Jeśli nie jesteś zadowolony z twardego kodowane połączenie-string, przyjrzeć this artykułu.