web-dev-qa-db-ja.com

ASP.NET Core 2 Seed Database

私はこれに関してSOで同様の例をいくつか見ましたが、私が間違っていることを理解するための言語についてはまだ十分に知りません。詳細については、データベースのシードに問題があります。

次のエラーが表示されます。

InvalidOperationException:ルートプロバイダーからスコープサービス 'demoApp.Models.AppDbContext'を解決できません。

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

問題の3つのファイルは次のとおりです。

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

誰かが私が間違っていることと状況を改善する方法を説明するのを助けることができますか?

12
forcequitIO

ASP.NET Core 2.0では、次の変更が推奨されます。 (startup.csのシードはCore 1.xで機能します。2.0ではProgram.csに進み、Mainメソッドを変更して、アプリケーションの起動時に次のことを行います。依存関係注入コンテナーからデータベースコンテキストインスタンスを取得します。コンテキスト。シードメソッドが完了したらコンテキストを破棄します(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();
}
30
Les P

元の回答から更新:

.NET Core 2.0の場合は、代わりに this answer をチェックしてください

元の答え:

私も.NET Coreのエキスパートではありませんが、これがあなたのソリューションかもしれません。

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

エラーは、コンテキストのスコープが必要であることを示唆しています。

また、まだ行っていない場合は、 ASP.NET Coreの依存性注入の概要 docをご覧ください。より具体的には Service Lifetimes and Registrationオプション セクション。

7
Emmanuel