2017-09-14 85 views
5

我已經看到了一些關於這方面的類似例子,但我對這門語言還不夠了解,只是還沒有看到我做錯了什麼。我拼湊了一個演示來了解更多信息,但我在播種我的數據庫時遇到了麻煩。ASP.NET核心2種子數據庫

我收到以下錯誤:

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

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

這裏有三個文件有問題:

型號/ 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; } 
} 

型號/ 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 => {...}); 
} 

有人能幫忙解釋一下我做錯了,如何補救?

回答

11

在ASP.NET Core 2.0中,建議進行以下更改。 (startup.cs中的種子適用於Core 1.x. For 2.0請進入Program.cs,修改Main方法以在應用程序啓動時執行以下操作: 從依賴項注入容器中獲取數據庫上下文實例 調用種子方法,傳遞給它的上下文。 處置當種子法完成的上下文。 (下面是從微軟網站的樣本。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

爲什麼修改'Main'?有沒有提到這是最好的參考? –

+1

I t在上面的代碼下面的鏈接文章中提到它。 「在較老的教程中,您可能會在Startup.cs中的Configure方法中看到類似的代碼,我們建議您僅使用Configure方法來設置請求管道,應用程序啓動代碼屬於Main方法。 – palehorse

+0

注意:爲使CreateScope方法可用,需要使用以下using語句:'using Microsoft.Extensions.DependencyInjection;'。 – JohnLBevan

2

更新從原來的答案:

對於.NET 2.0的核心,看看this answer代替

原來的答案:

我不是.NET的核心專家任,但這可能是你的解決方案。

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

該錯誤表明上下文應當作用域。另外,如果你還沒有這樣做,我會看看Introduction to Dependency Injection in ASP.NET Core文檔,但更具體地說,Service Lifetimes and Registration Options部分。

+0

我重新進行了遷移,更新數據庫和數據庫播種預期。我非常感謝你提供的鏈接。非常感謝你。 – forcequitIO