2

In my Core 1.0 app, Startup ctor loaded several extra json files into the configuration...

public Startup(IHostingEnvironment env) {
    Environment = env;

    var builder = new ConfigurationBuilder()
        .SetBasePath(env.ContentRootPath)
        .AddJsonFile("appsettings.json")
        .AddJsonFile($"appsettings.{env.EnvironmentName}.json")
        .AddJsonFile($"activityGroups.{env.EnvironmentName}.json")
        .AddEnvironmentVariables();

    Configuration = builder.Build();
}

Then in ConfigureServices, I grabbed the data from these out of the config into strongly typed lists...

public void ConfigureServices(IServiceCollection services) {
    services.AddDbContext<Models.DbContext>(
        options => options.UseSqlServer(
            Configuration["Data:DefaultConnection:ConnectionString"]
        )
    );

    services.AddScoped<Repository>();
    services.AddTransient<DbSeed>();
    services.AddOptions();

    services.Configure<List<Models.Task>>(Configuration.GetSection("ActivityGroups"));
}

Then, in Configure, the strongly typed list was injected and use for db init..

public void Configure(
    IApplicationBuilder app,
    DbSeed seed,
    ILoggerFactory logging,
    IOptions<List<ActivityGroup>> activityGroupConfig
    ) {

    app.UseAuthentication();
    app.UseMvc();

    bool seedDb;
    bool.TryParse(Configuration.GetSection("SeedDb").Value, out seedDb);
    if (seedDb) {
        seed.EnsureSeeded(activityGroupConfig.Value);
    }
}

However...

In 2.0 projects, move the SeedData.Initialize call to the Main method of Program.cs...

As of 2.0, it's bad practice to do anything in BuildWebHost except build and configure the web host. [configure web host includes data seeding?] Anything that's about running the application should be handled outside of BuildWebHost — typically in the Main method of Program.cs.
https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#move-database-initialization-code

Yet, in "new" Main(string[] args) we don't have access to the dbcontext (until Startup.ConfigureServices). Even if in the SeedData.Initialize(services); call as above in the MS documentation, how would SeedData have access to the connection string that is not defined until later in configure services?

The adoption of this new 2.0 pattern is highly recommended and is required for product features like Entity Framework (EF) Core Migrations to work.
https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#update-main-method-in-programcs

I've been googling and digging through docs and samples (that example seeds with hardcoded values) without getting a clear picture (yet) of the expectations or recommended design (beyond, "dont do what you did previously".)

Anyone here more familiar or experienced with how to do database seeding from json on disk in ASP.NET Core 2.0?

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
t.j.
  • 1,227
  • 3
  • 16
  • 30
  • You're doing it in the right spot. The doco says 'don't do it in `BuildWebHost`', and you're doing it in `Configure()`. Where did you get this `DbSeed` class from? – zaitsman Feb 09 '18 at 04:22
  • @zaitsman The [docs mention](https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/#move-database-initialization-code), "In 2.0 projects, move the SeedData.Initialize call to the Main method of Program.cs:" I'm just not sure how. – t.j. Feb 09 '18 at 21:11
  • Currently, execution order goes: `Program.Main()`, `Program.BuildWebHost()`, `Startup.ConfigureServices()`, then `Startup.Configure()`. So I imagine by the time `Startup` is complete, all the services are configured. But `Main(args)` cant be DI aware since `Program.Main` must have a specific signature... right? – t.j. Feb 09 '18 at 22:25

1 Answers1

1

So, with help from this SO question, I got the gist of getting the services from within Program.cs

public class Program {
    public static void Main(string[] args) {
        var host = BuildWebHost(args);

        using (var scope = host.Services.CreateScope())
        {
            var services = scope.ServiceProvider;
            var logger = services.GetRequiredService<ILoggerFactory>();

            var ctx = services.GetRequiredService<DataContext>();
            // Now I can access the DbContext, create Repository, SeedData, etc!

Now, the problem is in trying to figure out how to access values from appsettings.json, new SO question here.

t.j.
  • 1,227
  • 3
  • 16
  • 30