skip to Main Content

I should point out I’m new to .NET…

I have the following appsettings.json file:

{
    "Logging": {
        "LogLevel": {
            "Default": "Information",
            "Microsoft": "Warning",
            "Microsoft.Hosting.Lifetime": "Information"
        }
    },
    "ConnectionStrings": {
        "MyContext": "Host=localhost;Database=test;Username=user;Password=''"
    }
}

In the MyContext.cs file I want to read the connection string from the appsettings.json config:

using Microsoft.EntityFrameworkCore;
using System;
using System.Configuration;

namespace My.Models
{
  public partial class MyContext : DbContext
  {

  protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
  {
    Console.WriteLine(ConfigurationManager.ConnectionStrings.Count);
    if (!optionsBuilder.IsConfigured)
    {
  optionsBuilder.UseNpgsql(ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString);
    }
  }
}

But ConfigurationManager.ConnectionStrings["MyContext"].ConnectionString is null, any ideas why?

I’m using the config file successfully in Startup.cs via Configuration.GetConnectionString("MyContext"), but here I want to read the connection string from this config for situations outside of the ASP.NET application (i.e. in EF migrations I want to do using var db = new MyContext();), but have no idea why the above is returning null.

Is ConfigurationManager not reading from my appsettings.json file? Not sure how to tell, as ConfigurationManager.ConnectionStrings.Count returns 1, so I’m pretty confused. Is there anything obviously wrong someone can see?

I’m using .NET Core 5 and EF Core version 5

2

Answers


  1. the common way to define connection string in ef core is

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
    optionsBuilder.UseNpgsql(@"Host=localhost;Database=test;Username=user;Password=password");
    }
    

    You can access to IConfiguration manually:

    1. install this packages into ef project
    Microsoft.Extensions.Configuration
    Microsoft.Extensions.Configuration.Json
    
    1. build the IConfiguration
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            IConfigurationRoot configuration = new ConfigurationBuilder()
                .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
                .AddJsonFile("appsettings.json")
                .Build();
            optionsBuilder.UseNpgsql(configuration.GetConnectionString("DefaultConnection"));
        }
    

    if your Ef core is in a special project, you will have to copy appsetings.json to this project

    if you have a problem to find appsetings folder you can define a path directly

    // .SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
       .AddJsonFile(@"C:....appsettings.json")
    
    Login or Signup to reply.
  2. I’m assuming that you’re running either an API or a Blazor/Razor application since you mentioned a Startup.cs file 🙂

    The recommendation (official docs about this), in this case, is to use Entity Framework’s own libraries to setup your MyContext within Startup.ConfigureServices. There you’ll have access to both the ConnectionStrings within your application’s IConfiguration and to extension methods that allow you to register a DbContext with a specific connection string.

    It’ll probably look something like this, just adapt from my call to Sqlite into whatever Database driver you’re using:

    
    public class Startup 
    {
      Startup(IConfiguration configuration)
      {
        _configuration = configuration;
      }
    
      void ConfigureServices(IServiceCollection services) 
      {
        // Other dependencies go here
        string connString = _configuration.GetConnectionString("MyContext");
        services.AddDbContext<MyContext>(opt => opt.UseSqlite(connString));
        // Other dependencies, et cetera
      }
    }
    
    

    This allows you to keep the Configuration logic from "leaking" into your "Model" namespace, thus your MyContext concern is just related to persistence of data and not accessing system files and environment variables.

    In order to use an Instance of MyContext on a Controller or anything else created by .NET’s dependency injection system all you need to do is ask for it within a class’ constructor, like:

    public class MyAwesomeController : ControllerBase
    {
      private readonly MyContext _context;
    
      // This tells .NET to inject an instance of MyContext into your controller
      public MyAwesomeController(MyContext context) 
      {
        _context = context ?? throw new ArgumentNullException();
      }
    
      // Now all you gotta do is actually use that instance - no matter where it's connecting to
      [HttpGet]
      public Task ListEverything() => _context.MySet.ToListAsync();
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search