2017-09-14 44 views
5

Widziałem kilka podobnych przykładów na temat SO, ale nie wiem wystarczająco dużo o tym języku, aby zobaczyć, co robię źle. Przygotowałem demo, aby dowiedzieć się więcej, ale mam problem z zaimportowaniem bazy danych.Baza ziarn ASP.NET Core 2

I pojawia się następujący błąd:

InvalidOperationException: Cannot resolve scoped service 'demoApp.Models.AppDbContext' from root provider.

Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteValidator.ValidateResolution(Type serviceType, ServiceProvider serviceProvider)

Oto trzy pliki w pytaniu:

modele/AppDbContext.cs

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

    } 
    public DbSet<Product> Products{ get; set; } 
    public DbSet<Category> Categories { get; set; } 
} 

models/DBInitializer.cs

public static class DbInitializer 
{ 
    public static void Seed(IApplicationBuilder applicationBuilder) 
    { 
     //I'm bombing here 
     AppDbContext context = applicationBuilder.ApplicationServices.GetRequiredService<AppDbContext>(); 

     if (!context.Products.Any()) 
     { 
      // Add range of products 
     } 

     context.SaveChanges(); 
    } 

    private static Dictionary<string, Category> _categories; 
    public static Dictionary<string, Category> Categories 
    { 
     get 
     { 
      if (_categories == null) 
      { 
       // Add categories... 
      } 

      return _categories; 
     } 
    } 
} 

Startup.cs

public Startup(IConfiguration configuration) 
{ 
    Configuration = configuration; 
} 

public IConfiguration Configuration { get; } 

public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddTransient<ICategoryRepository, CategoryRepository>(); 
    services.AddTransient<IProductRepository, ProductRepository>(); 

    services.AddDbContext<AppDbContext>(options => 
     options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); 

    services.AddMvc(); 
} 

public void Configure(IApplicationBuilder app, IHostingEnvironment env) 
{ 
    if (env.IsDevelopment()) 
    { 
     app.UseDeveloperExceptionPage(); 
     app.UseBrowserLink(); 
     app.UseStatusCodePages(); 

     // Kersplat! 
     DbInitializer.Seed(app); 
    } 
    else ... 

    app.UseStaticFiles(); 
    app.UseMvc(routes => {...}); 
} 

Czy ktoś może pomóc wyjaśnić, co robię źle i jak zaradzić tej sytuacji?

Odpowiedz

11

W środowisku ASP.NET Core 2.0 zaleca się następujące zmiany. (Rozsiewanie w startup.cs działa dla Core 1.x. W wersji 2.0 przejdź do pliku Program.cs, zmodyfikuj metodę Main, aby podczas uruchamiania aplikacji wykonać następujące czynności: Uzyskaj instancję kontekstu bazy danych z kontenera do wstrzykiwania zależności Wywołanie metody seed , przekazując jej kontekst. utylizować kontekst gdy metoda nasienie jest wykonywana. (Oto próbka z witryny firmy Microsoft. https://docs.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro)

public static void Main(string[] args) 
{ 
var host = BuildWebHost(args); 

using (var scope = host.Services.CreateScope()) 
{ 
    var services = scope.ServiceProvider; 
    try 
    { 
     var context = services.GetRequiredService<yourDBContext>(); 
     DbInitializer.Seed(context);//<---Do your seeding here 
    } 
    catch (Exception ex) 
    { 
     var logger = services.GetRequiredService<ILogger<Program>>(); 
     logger.LogError(ex, "An error occurred while seeding the database."); 
    } 
} 

host.Run(); 
} 
+0

Dlaczego modyfikowanie 'Main'? Jest tam jakieś odniesienie, gdzie jest wspomniane, że jest to preferowane? –

+1

I t wspomina o tym w połączonym artykule tuż poniżej kodu z góry. "W starszych samouczkach możesz zobaczyć podobny kod w metodzie Configure w Startup.cs. Zalecamy użycie metody Configure tylko do skonfigurowania potoku żądania Kod uruchamiania aplikacji należy do metody Main." – palehorse

+0

UWAGA: Wymaga użycia następującej instrukcji użycia, aby metoda CreateScope była dostępna: 'using Microsoft.Extensions.DependencyInjection;'. – JohnLBevan

2

Aktualizacja z oryginalnego odpowiedź:

NET Rdzenia 2.0 Sprawdź this answer zamiast

Original Odpowiedź:

nie jestem ekspertem NET rdzenia albo, ale ten może być twoim rozwiązaniem.

W DBInitializer.cs

public static void Seed(IApplicationBuilder applicationBuilder) 
    { 
     using (var serviceScope = applicationBuilder.ApplicationServices.GetRequiredService<IServiceScopeFactory>() 
       .CreateScope()) 
     { 
      AppDbContext context = serviceScope.ServiceProvider.GetService<AppDbContext>(); 

      if (!context.Products.Any()) 
      { 
       // Seed Here 
      } 

      context.SaveChanges(); 
     } 
    } 

Błąd sugeruje, że kontekst powinien być objęty zakresem.

Ponadto, jeśli jeszcze tego nie zrobiłeś, zajrzałbym do dokumentu Introduction to Dependency Injection in ASP.NET Core, ale dokładniej do sekcji Service Lifetimes and Registration Options.

+0

i reran migracje, uaktualnione bazy danych i bazy danych zaszczepiono zgodnie z oczekiwaniami Bardzo doceniam linki, które podałeś Dziękuję bardzo – forcequitIO