ASP.NET Core 2 Seed Database [duplicate]

Deadly 提交于 2019-12-18 10:45:00

问题


I've seen some of the similar examples on SO regarding this but I don't know enough about the language just yet to see what I'm doing wrong. I've cobbled together a demo to learn more but I'm having trouble seeding my database.

I receive the following error:

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

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

Here are the three files in question:

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

Can someone help explain what I'm doing wrong and how to remedy the situation?


回答1:


In ASP.NET Core 2.0 the following changes are recommended. (Seeding in startup.cs works for Core 1.x. For 2.0 go into Program.cs, modify the Main method to do the following on application startup: Get a database context instance from the dependency injection container. Call the seed method, passing to it the context. Dispose the context when the seed method is done. (Here's a sample from the Microsoft site. 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();
}



回答2:


Update From Original Answer:

For .NET Core 2.0, Check out this answer instead

Original Answer:

I'm no .NET Core expert either, but this might be your solution.

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

The error suggests that the context should be scoped.

Also, If you haven't done so already, I'd take a look at the Introduction to Dependency Injection in ASP.NET Core doc, but more specifically, the Service Lifetimes and Registration Options section.



来源:https://stackoverflow.com/questions/46222692/asp-net-core-2-seed-database

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!