web-dev-qa-db-fra.com

ASP.NET Core 2 Seed Database

J'ai vu quelques exemples similaires sur SO à ce sujet mais je ne connais pas encore assez la langue pour voir ce que je fais mal. J'ai bricolé une démo pour en savoir plus, mais j'ai du mal à amorcer ma base de données.

Je reçois l'erreur suivante:

InvalidOperationException: impossible de résoudre le service de portée 'demoApp.Models.AppDbContext' du fournisseur racine.

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

Voici les trois fichiers en question:

Modèles/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; }
}

Modèles/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 => {...});
}

Quelqu'un peut-il aider à expliquer ce que je fais mal et comment remédier à la situation?

12
forcequitIO

Dans ASP.NET Core 2.0, les modifications suivantes sont recommandées. (L'amorçage dans startup.cs fonctionne pour Core 1.x. Pour 2.0, accédez à Program.cs, modifiez la méthode Main pour effectuer les opérations suivantes au démarrage de l'application: obtenir une instance de contexte de base de données à partir du conteneur d'injection de dépendances. Appelez la méthode d'amorçage, en passant pour lui le contexte. Éliminer le contexte lorsque la méthode de départ est terminée. (Voici un exemple du site 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

Mise à jour à partir de la réponse d'origine:

Pour .NET Core 2.0, consultez cette réponse à la place

Réponse originale:

Je ne suis pas non plus un expert .NET Core, mais cela pourrait être votre solution.

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

L'erreur suggère que le contexte doit être limité.

En outre, si vous ne l'avez pas déjà fait, je consulterais le document Introduction to Dependency Injection in ASP.NET Core , mais plus spécifiquement, le Service Lifetimes and Registration Options section.

7
Emmanuel