简体   繁体   中英

Dependency Injection with configuration in .net core

I am trying to inject dependency by getting configuration in class in .net core project. The class where I am trying to inject dependency is in another project. But somehow I am not able to get the values from config file in injected dependency. Below is my code

In below DBContext I need to obtain value from configuration, where i have used DI of DBConfiguration class.

public class DBContext : DbContext
    {
        private readonly DBConfiguration _dBConfiguration;

        public DBContext(DBConfiguration dBConfiguration)
        {
            _dBConfiguration = dBConfiguration;
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer(_dBConfiguration.ConnectionString);
            base.OnConfiguring(optionsBuilder);
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }

And my StartUp.cs file in web api

public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<DBConfiguration>();

            services.AddEntityFrameworkSqlServer().AddDbContext<DBContext>();

            services.AddOptions();

            services.Configure<DBConfiguration>(Configuration.GetSection("DBConfiguration"));

            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
        }

and my appsettings.json file

{
  "DBConfiguration": {


         "ConnectionString": "Server=myserver;Database=BaseProjectDB;Trusted_Connection=True;MultipleActiveResultSets=true",
         "ApplicationName": "WebAPI"


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

Any help on this appreciated !

You seem to be using DBConfigurationOptions in your StartUp file, while you're injecting DBConfiguration in your DBContext.

This is how I currently use my configuration:

public class Startup
{
    private readonly IConfiguration _configuration;

    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
            .AddEnvironmentVariables();

        _configuration = builder.Build();
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.Configure<DBConfigurationOptions>(_configuration.GetSection("DBConfiguration"));
    }
}

and then it's injected as:

public class DBContext : DbContext
{
    private readonly DBConfigurationOptions _dBConfiguration;

    public DBContext(IOptions<DBConfigurationOptions> dBConfiguration)
    {
        _dBConfiguration = dBConfiguration.Value;
    }
}

Why don't you configure the db directly in the place you also have the configuration?
In your DBContext class (btw you should probably choose a better name for that) you just need to expose a constructor like this, no need for overriding OnConfiguring or anything like that.

This class can be in any assembly you want.

class DBContext : DbContext
{
    public DBContext(DbContextOptions<DBContext> options) : base(options)
    {
    }
}

For the configuration you can just use the built in optionsBuilder-action (place inside the ConfigureServices method):

services.AddEntityFrameworkSqlServer()
    .AddDbContext<DBContext>(optionsBuilder =>
        optionsBuilder.UseSqlServer(
            Configuration.GetSection("DBConfiguration").Get<DBConfiguration>().ConnectionString)
    );

Currently the way you get the configuration can definitely be improved. For example you could do something like this:

var DBConfig = Configuration.GetSection("DBConfiguration").Get<DBConfiguration>();
services.AddSingleton(DBConfig);// <- now you can inject that if you want but it's not necessary

// now we don't need to get the config here
services.AddEntityFrameworkSqlServer()
    .AddDbContext<DBContext>(optionsBuilder =>
        optionsBuilder.UseSqlServer(DBConfig.ConnectionString)
    );

There are some other things you might want to improve like better naming for DBContext and not overriding members you don't have a specific implementation for (like you did with OnModelCreating ).

Also for a next time you should include all the classes that aren't part of some sort of public API like your DBConfiguration class.

To receive the configuration, you have to modify the signature of your constructor in DBContext from

public DBContext(DBConfiguration dBConfiguration)

to

public DBContext(IOptions<DBConfiguration> dBConfiguration)

to receive the option properly (don't forget to add the namespace Microsoft.Extensions.Options ).

Additionally, you need to define the DBConfiguration class somewhere with the properties you have in your configuration file.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM