1

I am using the code below to retrieve the connection string and it works fine. However, the configuration object has to be passed through the layers. Previous versions of .Net would allow me to get the connection string directly in the data layer. So can I still do that (and how do I do that) or do I need to pass the configuration object through the application as I do now?

In startup.cs

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services)
{
   ...
   services.AddSingleton(_ => Configuration);
   ...
}

MyController.cs

public class MyController : Controller
{
  protected readonly IConfiguration Configuration;

  public MyController(IConfiguration configuration)
  {
     Configuration = configuration;
  }

  public IActionResult ListRecords()
  {
      DatabaseContext ctx = new DatabaseContext(Configuration);
      return View();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
   private readonly IConfiguration config;
   public DatabaseContext(IConfiguration config)
   {
      this.config = config;
   }

   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
      optionsBuilder.UseSqlServer(config["ConnectionStrings:Dev"]);
   }
}
2
  • You would do that in the Startup class. Virtually every example found on the internet does it. Commented Dec 3, 2020 at 14:30
  • 1
    You should be injecting your database context, not manually creating one. This way it's all configured from the startup class Commented Dec 3, 2020 at 14:39

3 Answers 3

1

Having to explicitly inject IConfiguration is usually seen as a code smell and indicates design issues.

Take advantage of dependency injection

public class MyController : Controller {
    DatabaseContext context;

    public MyController(DatabaseContext context) {
        this.context = context;
    }

    public IActionResult ListRecords() {
        //...use context here
        return View();
    }
}

and inject the database options instead

public class DatabaseContext : DbContext {    
    public DatabaseContext(DbContextOptions<DatabaseContext> options): base(options) {
        //...
    }
}

Then it is only a matter of configuring the context at startup

public IConfiguration Configuration { get; }

public void ConfigureServices(IServiceCollection services) {
    // ...

    services.AddDbContext<DatabaseContext>(options => 
        options.UseSqlServer(Congiguration.GetConnectionString("Dev"));

    // ...
}
Sign up to request clarification or add additional context in comments.

7 Comments

thanks and now what happens in the controller if I call other layers such as a business layer - do I pass the context or can their classes be invoked with it as a parameter via DI
Actually, this question is asked here: stackoverflow.com/questions/40862162/…
If the business layer classes need the context, again use DI and inject the context into the BL via constructor injection and inject the BL class into the controller.
that makes a lot of sense on injecting the BL into the controller but how do I inject the context into the BL? Do I use AddDbContext but don't have a BL constructor with a DBContext?
@user3807918 I think you misunderstood what I meant. Do use AddDbContext and do have a BL class with the context in its constructor. When the framework is injecting the BL class into the controller, it will also create the context and inject it into the BL class.
|
1

Typically the pattern I've used for setting up DBContext, is to configure at startup.

So if this is startup.cs:

        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            var sqlConnString = Configuration.GetConnectionString(dbConnectionStringSettingsName);

            services.AddDbContext<DatabaseContext >(opt => opt.UseSqlServer(sqlConnString));

Also, if you pass your context as a service reference, you shouldn't need to give it IConfiguration.

    private readonly DatabaseContext _context;       

    public MyController(DatabaseContext context)
    {
        _context = context;
    }
    public IActionResult ListRecords()
    {
      var dbresults = _context.Table.ToList();
      return View(dbresults );
    }

1 Comment

I agree, why wouldn't you use the Startup to do this...
0

use nugget packaeges

Install-Package Microsoft.Extensions.Configuration.Abstractions

 Install-Package Microsoft.Extensions.Configuration

and then Inject IConfigurationSection in the web application.

https://github.com/geeksarray/read-appsettings-json-in-net-core-class-library-using-dependency-injection

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.