0

I checked some related questions, like this or this but they don't really seem to answer my question. I have a simple Client <=> Server application. For local development I want to store the connection string in Secrets Manager (secrets.json) outside the project.

When I try to inject the IConfiguration in a DB Context, it is empty in one of the projects - and when trying to read the connection string I get an error messsage:

System.ArgumentNullException: 'Value cannot be null. Arg_ParamName_Name'

The strange thing is that I have two projects that look very, very similar - not to say the same - regarding this functionality. One works just fine, the other one does not.

This I have in Program.cs. The GetConnectionString method returns the correct connection string:

ConfigurationManager configuration = builder.Configuration; // allows both to access and to set up the config
IWebHostEnvironment environment = builder.Environment;

var ConnectionString = configuration.GetConnectionString("OPS_DB");
builder.Services.AddDbContext<TestContext>(options => options.UseSqlServer(ConnectionString));
builder.Services.AddSingleton<IConfiguration>(configuration);

In my DB context I have this. Calling GetConnectionString returns NULL here.

public partial class TestContext : DbContext
{
    IConfiguration configuration;

    public TestContext()
    {
    }

    public TestContext(DbContextOptions<TestContext> options, IConfiguration configuration)
        : base(options)
    {
        this.configuration = configuration;
    }

    public virtual DbSet<DbScalingLevels> DbScalingLevels { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        String _connStr = this.configuration.GetConnectionString("OPS_DB"); // NULL !!
        if (!optionsBuilder.IsConfigured)
        {
            optionsBuilder.UseSqlServer(_connStr);
        }
    }

This is my secret.json:

{
  "ConnectionStrings": {
    "OPS_DB": "Data Source=some connection string"
  }
}

As mentioned earlier, one project configured like this works just fine, another one does not. What is it I don't see here?

Put a (not) working example on GitHub.

Aileron79
  • 523
  • 5
  • 27
  • 2
    You don't need to register `IConfiguration`, the HostBuilder registers it by default. Why are you injecting `IConfiguration` into the DbContext though, when you've already configured it to use the connection string in `AddDbContext` ? – Panagiotis Kanavos Oct 12 '22 at 10:05
  • 1
    Wait what? .NET 6 and Visual Studio 2010? Are you sure???? – Peter Csala Oct 12 '22 at 10:26
  • @PanagiotisKanavos: Probably because I am not exactly sure how it is supposed to work, how would I get the Connection String in the Context - or how would I get the Context if not by `using(var context = new TestContext())`? Sorry, I'm not too familiar with the concept here. And: Still I wonder why I don't get the string from my secrets.json? – Aileron79 Oct 12 '22 at 10:56
  • @PeterCsala: Thx, that was a typo in the tags obviously - Fixed. – Aileron79 Oct 12 '22 at 10:56
  • 1
    The whole point of using `AddDbContext` is to *avoid* writing `new TestContext()`. In eg a Controller class, if you add `TestContext` as a constructor parameter the DI middleware will create a new TestContext based on the configuration specified in `AddDbContext`, using the connection string specified there – Panagiotis Kanavos Oct 12 '22 at 10:58
  • Yes, that works, thanks a lot - I believe I understand! The Context is automatically injected in the Controller classes and i can use it there. However, if I have a method in an entirely different class, I need to pass the context as a parameter. Is this how it is supposed to be done or does it make sense to create a new Context in some places? Still, what confuses me most is that I don't get the connection string from the secrets.json within the context using `this.configuration.GetConnectionString`. – Aileron79 Oct 12 '22 at 11:47
  • Have you solved the problem? – Lei Zhang-MSFT Oct 18 '22 at 01:42

1 Answers1

0

Thanks to PanagiotisKanavos for the reply.

IConfiguration desn't need to register because it is the default of Builder.

You can refer to this document. https://learn.microsoft.com/en-us/ef/core/miscellaneous/connection-strings?source=recommendations#aspnet-core

The context is typically configured in Startup.cs with the connection string being read from configuration. Note the GetConnectionString() method looks for a configuration value whose key is ConnectionStrings:. You need to import the Microsoft.Extensions.Configuration namespace to use this extension method.

Lei Zhang-MSFT
  • 280
  • 1
  • 5