How to get ConnectionString from appsettings.json into DA project?

1.4k Views Asked by At

So far I developed multiple ASP.NET Core Web applications using EFCore (3.1) where I had all layers (Model, DataAccess, BusinessLogic...) in the same project. In order to provide the database connection string to the DbContext, I used DependencyInjection and called AddDbContext in the ConfigureServices method like this:

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<DbContextName>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
    // ...
}

I then obtained an instance of the context via the constructor in each controller class and used it to interact with the database. The connection string was always stored in the appsettings.json file of the web application.

Now I am working on a more complex application based on EF 5 which contains individual projects for every layer, including one for the DataAccess layer. In order to avoid ending up with countless individual configuration files for every single project in the solution, I still want to store the database connection string in the appsettings.json file.

How can I provide the connection string from the appsettings.json file to the DbContext in the DataAccess project? Since I cannot access the configuration in the OnConfiguring method inside the DataAccess project, I cannot provide it that way. Is it still possible to do this via AddDbContext as before, or how is this usually done? All examples I can find so far just work with hardcoded connection strings, so this is never explained in any of them.

1

There are 1 best solutions below

2
denys-vega On

1. You can solve it by creating a singleton service to provide the connection string:

Define the IConnectionStringProvider interface in a shared project.

public interface IConnectionStringProvider
{
   public string DefaultConnectionString {get;}
}

In your web project, you will implement the service to provide the connection string.

public sealed class ConnectionStringProvider : IConnectionStringProvider
{
   private readonly IConfiguration _configuration;
   public ConnectionStringProvider(IConfiguration configuration)
   {
      _configuration = configuration;
   }

   public string DefaultConnectionString => _configuration.GetConnectionString("DefaultConnection");
}

Service registration:

public class Startup
{
   // ...
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddSingleton<IConnectionStringProvider,ConnectionStringProvider>();
      // ...
   }
   // ...
}

Finally you can inject IConnectionStringProvider in your DAL project, check the following example (assuming your class name is DAL).

public class DAL
{
   // ...
   private readonly IConnectionStringProvider _connectionStringProvider;
   
   public DAL(IConnectionStringProvider connectionStringProvider)
   {
      _connectionStringProvider = connectionStringProvider;
   }
   
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddDbContext<DbContextName>(options => options.UseSqlServer(_connectionStringProvider.DefaultConnectionString));
      // ...
   }
   // ...
}

Important note: The DAL class should be registered as a service.

2. Another approach is to create an extension method to register your DAL services and pass the IConfiguration interface as argument. Something like:

public static class DALServices
{
   public static IServiceCollection AddDALServices(this IServiceCollection services, IConfiguration configuration)
   {
      services.AddDbContext<DbContextName>(options => options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
      // ...
      return services;
   }
}

PS: You will need to install the Nuget package in your DAL project: Microsoft.Extensions.Configuration

Call the extension method from Starup class:

public class Startup
{
   // ...
   public void ConfigureServices(IServiceCollection services)
   {
      services.AddDALServices(IConfiguration);
      // ...
   }
   // ...
}