How to set connectionstring from appsettings.json in Entity Framework Core

.net-core c# entity-framework-core

Question

I'm setting up a new database with Entityframework Core and code first approach. I have set up a context class like in the code listing below and all needed classes for the database tables too. Now I want to create the new database with

using (var context = new MyContext())
{
    context.Database.EnsureCreated();
}

But what I get is an error, that the connectionstring cannot be null.

My Connectionstring is set in the appsettings.json file an I copy this to the output directory when the project builds.

I have tried different ways to get the connectionstring from the appsettings file but all with the same result. In the Configuration Property in the Startup class I can see that the appsettings file is loaded correctly but when I want to get the string with

ConnectionString = Configuration["Connectionstrings:MyConnection"];

the ConnectionString is allways null.

I have this in my Startup.cs File:

 public class Startup
 {
    public static string ConnectionString { get; private set; }
    public IConfigurationRoot Configuration { get; set; }

    public Startup(IHostingEnvironment _environment)
    {
        Configuration = new ConfigurationBuilder()
                        .SetBasePath(_environment.ContentRootPath)
                        .AddJsonFile("appsettings.json")
                        .Build();
    }

with the following in the Configure - Method

using (var context = new MyContext())
{
    context.Database.EnsureCreated();
}

And in my context class I have the following code

public class MyContext : DbContext
{
    public MyContext()
    {
    }

    public static string GetConnectionString()
    {
        return Startup.ConnectionString;
    }

protected override void OnConfiguring(DbContextOptionsBuilder _builder)
{
    _builder.UseSqlServer(GetConnectionString());
}

So now, when I start the application I get the error in the OnConfiguring - Method that the connectionstring cannot be null.

And my appsettings.json file is

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },

  "Connnectionstrings": {
    "MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
  },
}
1
2
5/7/2019 8:04:00 AM

Accepted Answer

The ConnectionString is allways null because there is a typo, try this

ConnectionString = Configuration["Connnectionstrings:MyConnection"];

or fix name in appsettings.json

4
5/7/2019 8:07:56 AM

Popular Answer

I can show you two options of how to pass connection string via strongly typed Settings class loaded from appsettings.json. For both you just need to move your config settings to custom section from default ConnnectionStrings one and fully control your DB settings and passing them to you EntityFramework context.

You need do this in Startup class:

private Settings _settings;
public Startup(IConfiguration configuration, ...)
{
    Configuration = configuration;
    ...
}

public IConfiguration Configuration { get; }
...
public void ConfigureServices(IServiceCollection services)
{
    services
        .AddOptions()
        .Configure<Settings>(Configuration.GetSection("Settings"))
        .AddSingleton(Configuration);

    _settings = Configuration.GetSection(nameof(Settings)).Get<Settings>();

    services.AddTransient<DesignTimeDbContextFactory>();

    services.AddDbContext<MyContext>(options =>
    {
        if (_settings.DatabaseSettings.UseInMemory)
        {
            options.UseInMemoryDatabase("DummyInMemoryDatabase");
        }
        else
        {
            // Option 1
            options.UseSqlServer(_settings.DatabaseSettings.BuildConnectionString());
            // Option 2
            options.UseSqlServer(_settings.ConnectionStrings.MyConnection);
        }
    });
    ...
}

This is the corresponding appsettings.json file:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },

  "Settings": {

    // Option 1: move connection strings to custom strong typed Settings class
    "ConnnectionStrings": {
      "MyConnection": "server=.;database=MyDatabase;trusted_connection=true;MultipleActiveResultSets=True"
    },

    // Option 2: store DB settings any custom way you like - also to get via strong typed Settings class
    "DatabaseSettings": {
      "UseInMemory": false,
      "Host": ".",
      "Name": "MyDatabase",
      "User": "qwerty",
      "Password": "@#$%*"
    }
  }
}

The strongly typed Settings class:

/// <summary> Represents settings configured in appsettings.json file </summary>
public class Settings
{
    /// <summary> Option 1: move connection strings to custom strong typed Settings class </summary>
    public Connections ConnectionStrings { get; set; }

    /// <summary> Option 2: store DB settings any custom way you like - also to get via strong typed Settings class </summary>
    public Database DatabaseSettings { get; set; }
}

public class Connections
{
    public string MyConnection { get; set; }
}

public class Database
{
    public bool UseInMemory { get; set; }
    public string Host { get; set; }
    public string Name { get; set; }
    public string User { get; set; }
    public string Password { get; set; }
    public string BuildConnectionString() => $"Server={Host};Database={Name};User Id={User};Password={Password}";
}

And helper class which is used for DB migrations and other design time code generations - DesignTimeDbContextFactory:

public class DesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyContext>
{
    public  MyContext CreateDbContext(string[] args)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(Path.Combine(Directory.GetCurrentDirectory()))
            .AddJsonFile("appsettings.json", optional: false);

        var config = builder.Build();

        var settingsSection = config.GetSection("Settings");
        var settings = new Settings();
        settingsSection.Bind(settings);

        var optionsBuilder = new DbContextOptionsBuilder<MyContext>()
            .UseSqlServer(settings.ConnectionStrings.MyConnection); // or you can use option #2 either

        return new MyContext(optionsBuilder.Options);
    }
}


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow