Не удается разрешить DbContext в ASP.NET Core 2.0

Прежде всего, я пытаюсь засеять мою базу данных образцами данных. Я прочитал, что это способ сделать это (в Startup.Configure) (см. База данных семантики Core RC2 ASP.NET)

Я использую ASP.NET Core 2.0 с параметрами по умолчанию.

Как обычно, я регистрирую DbContext в ConfigureServices. Но после этого в методе Startup.Configure, когда я пытаюсь разрешить его с помощью GetRequiredService, он выдает это сообщение:

System.InvalidOperationException: "Не удается разрешить работу с областью действия" SGDTP.Infrastructure.Context.SGDTPContext" от root провайдер.

Мой класс запуска такой:

public abstract class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<SGDTPContext>(options => options.UseInMemoryDatabase("MyDatabase"))
        services.AddMvc();
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();

        SeedDatabase(app);
    }

    private static void SeedDatabase(IApplicationBuilder app)
    {
        using (var context = app.ApplicationServices.GetRequiredService<SGDTPContext>())
        {
            // Seed the Database
            //... 
        }
    }
}

Что я делаю неправильно? Кроме того, это лучшее место для создания данных семян?

Ответ 1

Вы регистрируете SGDTPContext в качестве сервиса с областью действия, а затем пытаетесь получить к нему доступ за пределами области. Чтобы создать область внутри вашего метода SeedDatabase, используйте следующее:

using (var serviceScope = app.ApplicationServices.CreateScope())
{
    var context = serviceScope.ServiceProvider.GetService<SGDTPContext>();

    // Seed the database.
}

Благодарим @khellang за указание на метод расширения CreateScope в комментариях, за комментарий @Tseng и ответ о том, как реализовать заполнение в EF Core 2.

Ответ 2

Эта ошибка получалась при чтении официального учебного пособия по ASP.Net MVC Core, в разделе, где вы должны добавить затравочные данные в свое приложение. Короче говоря, добавив эти две строки

 using Microsoft.EntityFrameworkCore;
 using Microsoft.Extensions.DependencyInjection;

чтобы класс SeedData решил это за меня:

using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Linq;

namespace MvcMovie.Models
{
public static class SeedData
{
    public static void Initialize(IServiceProvider serviceProvider)
    {
        using (var context = new MvcMovieContext(

           serviceProvider.GetRequiredService<DbContextOptions<MvcMovieContext>>()))
        {
            // Look for any movies.
            if (context.Movie.Any())
            {
                return;   // DB has been seeded
            }
  ...

Не могу сказать, ПОЧЕМУ, но это были два варианта, которые я получил после выбора варианта быстрого исправления Alt + Enter.

Ответ 3

public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        var key = Encoding.ASCII.GetBytes(Configuration.GetSection("AppSettings:Token").Value);
        services.AddDbContext<DataContext>(x => x.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")).EnableSensitiveDataLogging());
        services.AddMvc();
        services.AddTransient<Seed>();
        services.AddCors();
        services.AddScoped<IAuthRepository, AuthRepository>();
        services.AddScoped<IUserRepository, UserRepository>();
        services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(Options =>
            {
                Options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(key),
                    ValidateIssuer = false,
                    ValidateAudience = false
                };
            }

        );

    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env ,Seed seeder)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler(builder =>
            {
                builder.Run(async context =>
                {
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                    context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
                    var error = context.Features.Get<IExceptionHandlerFeature>();
                    if (error != null)
                    {
                        context.Response.AddApplicationError(error.Error.Message);
                        await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
                    }
                });
            });
        }
        seeder.SeedUser();
        app.UseCors(x=>x.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().AllowCredentials());
        app.UseMvc();
    }
}

}