ASP.NET Core 2种子数据库

时间:2017-09-14 15:11:03

标签: c# asp.net .net .net-core-2.0

我已经在SO上看到了一些类似的例子,但我还没有充分了解这种语言,看看我做错了什么。我已经拼凑了一个演示程序以了解更多信息,但我在播放数据库时遇到了问题。

我收到以下错误:

  

InvalidOperationException:无法解析作用域服务' demoApp.Models.AppDbContext'来自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 => {...});
}

有人可以帮助解释我做错了什么以及如何纠正这种情况吗?

2 个答案:

答案 0 :(得分:29)

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

答案 1 :(得分:7)

从原始答案更新:

对于.NET Core 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部分。