1

Environment:

<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.7" />

SQL Server 2016
.NET Core 3.1

I have a working snippet of a console application below that gets connection string out of appsettings but it feels like I have too much code and I should be able to combine some of this but not sure how.

class Program
{
    static void Main(string[] args)
    {
        CreateHostBuilder(args);
    }

    public static void CreateHostBuilder(string[] args)
    {
        IConfiguration config = new ConfigurationBuilder()
            .AddJsonFile(Path.Combine(Directory.GetCurrentDirectory(), "appsettings.json"), true, true)
            .Build();

        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices((context, services) =>
            {
                services.AddTransient<App>();
                services.AddDbContext<SchoolContext>(options =>
                options.UseSqlServer(config["ConnectionStrings:MyDatabase"]));
            })
            .Build();

        ActivatorUtilities.CreateInstance<Startup>(host.Services);
    }
}

Update
Based on @andy's answer below...

class Program
{
    static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        host.RunAsync().GetAwaiter();

        ActivatorUtilities.CreateInstance<Startup>(host.Services);
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args).ConfigureServices((context, services) =>
        {
            var config = context.Configuration; // grab from here
            services.AddTransient<App>();
            services.AddDbContext<SchoolContext>(options =>
            options.UseSqlServer(config["ConnectionStrings:MyDatabase"]));
        });
}
Rod
  • 14,529
  • 31
  • 118
  • 230

1 Answers1

4

You already created a default builder which includes your appsettings.json file. You can get at it by grabbing it from the context in ConfigureServices

class Program
{
    static Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        return host.RunAsync();
    }

    /* or you can use a synchronous main:
    static void Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        host.Run();
    }
    */

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args).ConfigureServices((context, services) =>
        {
            var config = context.Configuration; // grab from here
            services.AddTransient<App>();
            services.AddDbContext<SchoolContext>(options =>
                options.UseSqlServer(config["ConnectionStrings:MyDatabase"]));
        });
}

I also refactored your code a bit to show you a typical create/build/run scenario with a generic host.

ETA

Here is some shameless self-promotion: I came up with a way to move this logic to the good ol' IWebHostBuilder/Startup.cs pattern that we all know and love. If interested, check this out.

Andy
  • 12,859
  • 5
  • 41
  • 56
  • Thanks @Andy, I updated OP and have a couple questions...1) what does ```host.RunAsync()``` do because I can comment it out and the very little code that have still works. 2) I still need to have the ```ActivatorUtilities``` part, correct? – Rod Sep 04 '20 at 15:50
  • 1
    @Rod 1. `host.RunAsync()` actually runs your web-server. 2. no, you don't need it. instead I recommend use this: `Host.ConfigureWebHostDefaults(hostBuilder => hostBuilder.UseStartup())` – iTKerry Sep 04 '20 at 16:04
  • 1
    @Rod -- to tell you the truth, I have never seen `ActivatorUtilities` ever used in my life and i have no idea what it does. `RunAsync` simply runs your host and "blocks" until it closes. The code above should be all you need. Try using it instead of the `ActivatorUtilities` and see if it does what you need. – Andy Sep 04 '20 at 16:04
  • 1
    @iTKerry -- he isn't using `IWebHostBuilder`. He is using a generic host. It doesn't have a `UseStartup` extension. – Andy Sep 04 '20 at 16:05
  • Yeah, I apologize for failing to mention this is a console application. I ald that to OP. – Rod Sep 04 '20 at 16:33
  • @Rod -- i would just remove that `ActivatorUtilities` line.. it's not doing anything. Also, it should be `host.RunAsync().GetAwaiter().GetResult();` or just do `host.Run();` I updated my answer to show async and sync versions. – Andy Sep 04 '20 at 16:50
  • But then how do I start an instance of ```Startup``` or ```App``` class if I remove the ```ActivatorUtilities```? – Rod Sep 04 '20 at 16:52
  • @Rod -- a generic host doesn't use `Startup` -- Whatever code is in there will never be called. Set a breakpoint on `ConfigureServices` in your `Startup.cs` and see if it ever gets hit. Anyway, if you need a `Startup` pattern, then you need to use `IWebHostBuilder`. What does startup it do? – Andy Sep 04 '20 at 16:56