58

First of all, I'm trying to seed my database with sample data. I have read that this is the way to do it (in Startup.Configure) (please, see ASP.NET Core RC2 Seed Database)

I'm using ASP.NET Core 2.0 with the default options.

As usual, I register my DbContext in ConfigureServices. But after that, in the Startup.Configure method, when I try to resolve it using GetRequiredService, it throws with this message:

System.InvalidOperationException: 'Cannot resolve scoped service 'SGDTP.Infrastructure.Context.SGDTPContext' from root provider.'

My Startup class like this:

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
            //... 
        }
    }
}

What am I doing wrong? Also, is this the best place to create seed data?

SuperJMN
  • 13,110
  • 16
  • 86
  • 185

3 Answers3

106

You're registering SGDTPContext as a scoped service and then attempting to access it outside of a scope. To create a scope inside your SeedDatabase method, use the following:

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

    // Seed the database.
}

Credit to @khellang for pointing out the CreateScope extension method in the comments and to @Tseng's comment and answer re how to implement seeding in EF Core 2.

Kirk Larkin
  • 84,915
  • 16
  • 214
  • 203
  • 3
    _does appear to continue to be the recommended approach for seeding from what I have seen_ Well, not exactly. Using scoped yes, but not inside Configure method, do to the way EF Core 2.0 does discovery and instantiation of DbContext at design time. See https://stackoverflow.com/a/45942026/455493 for the currently recommended approach. If you keep doing seeding in `Configure` method, then running `dotnet ef migrations` or `dotnet ef database update` will also execute the seeding, something you pretty much don't want when running the command line tools – Tseng Sep 05 '17 at 23:10
  • 2
    Just FYI; there's [a `CreateScope` extension method directly on `IServiceProvider`](https://github.com/aspnet/DependencyInjection/blob/88c3bd6fe2786dd759b4a6c6d7c410e895336b6c/src/DI.Abstractions/ServiceProviderServiceExtensions.cs#L120-L128), so you can cut `.GetRequiredService()` and just call that directly :) – khellang Sep 06 '17 at 05:28
1

Was getting this error while following the official ASP.Net MVC Core tutorial, in the section where you are supposed to add seeded data to your application. Long story short, adding these two lines

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

to the SeedData class solved it for me:

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
            }
  ...

Can't tell you the WHY, but these were two of the options I got from following the Alt + Enter quick fix option.

Ojonugwa Jude Ochalifu
  • 26,627
  • 26
  • 120
  • 132
  • 2
    For me work with serviceProvider.CreateScope().ServiceProvider.GetRequiredService>(); – Zaha Oct 05 '19 at 00:12
-1
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();
    }
}

}

SinaNasiri
  • 83
  • 2
  • 3