Reputation: 1569
In my solution, I have a ASP.NET Core web project and a .NET Standard class library project. Class library project is the data access layer and I want to read the connection string from my appsettings.json (ASP.NET Core project) in my data access layer.
I have found few answers such as by Andrii Litvinov which looks like quite straight forward to implement but he also mentioned about implementing through Dependency Injection. I don't want to choose the easy shortcut way but looking for the dependency injection implementation?
I am not sure if having appsettings.json in my class library and then registering it through IConfigurationRoot is the better option (as explained here by JRB) but in my scenario, the connection string is in the appsettings.json file of the web project and I wan't constructor dependency injection implementation in my class library project to consume the connection string.
Upvotes: 7
Views: 16659
Reputation: 2259
This was solved for me in my program.cs file just adding this:
builder.Services.AddDbContext<YourContextClassHere>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("Web_Project_app_settings_connection_string_here"));
});
Upvotes: 0
Reputation: 151
It's pretty simple...use IOptions at the composition root like so in startup.cs or in a separate class library project:
services.AddScoped<IDbConnection, OracleConnection>();
services.AddScoped<IDbConnection, SqlConnection>();
services.Configure<DatabaseConnections>(configuration.GetSection("DatabaseConnections"));
services.AddScoped(resolver =>
{
var databaseConnections = resolver.GetService<IOptions<DatabaseConnections>>().Value;
var iDbConnections = resolver.GetServices<IDbConnection>();
databaseConnections.OracleConnections.ToList().ForEach(ora =>
{
ora.dbConnection = iDbConnections.Where(w => w.GetType() == typeof(OracleConnection)).FirstOrDefault();
ora.dbConnection.ConnectionString = ora.ConnectionString;
//ora.Guid = Guid.NewGuid();
});
databaseConnections.MSSqlConnections.ToList().ForEach(sql =>
{
sql.dbConnection = iDbConnections.Where(w => w.GetType() == typeof(SqlConnection)).FirstOrDefault();
sql.dbConnection.ConnectionString = sql.ConnectionString;
//sql.Guid = Guid.NewGuid();
});
return databaseConnections;
});
Above uses the Configuration class to map the appsettings.json section that houses your connection strings. Here's an example of the appsettings.json file:
"DatabaseConnections": {
"OracleConnections": [
{
"Alias": "TestConnection1",
"ConnectionString": "Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = ) (PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ) ) );User Id=;Password=;"
},
{
"Alias": "TestConnection2",
"ConnectionString": "Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = ) (PORT = 1521)) (CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = ) ) );User Id=;Password=;"
}
],
"MSSqlConnections": [
{
"Alias": "Music",
"ConnectionString": "Data Source=(LocalDB)\\MSSQLLocalDB;AttachDbFilename=C:\\Users\\MusicLibrary.mdf;Integrated Security=True;Connect Timeout=30"
}
]
}
IOptions now gives me the ability to set my connection string at runtime in startup.cs close to the composition root.
Here's my class I'm using to map my connection strings:
public class DatabaseConnections : IDatabaseConnections
{
public IEnumerable<Connection> OracleConnections { get; set; }
public IEnumerable<Connection> MSSqlConnections { get; set; }
}
Now any service layer has access to multiple db connections and provider per request!
Github project: https://github.com/B-Richie/Dapper_DAL
Upvotes: 0
Reputation: 38499
You can inject an instance of a class that implements IConfiguration
See Here
Let's assume in your .net core app, you have a configuration file that looks something like this:
{
"App": {
"Connection": {
"Value": "connectionstring"
}
}
}
In your data access layer (class library) you can take a dependency on IConfiguration
public class DataAccess : IDataAccess
{
private IConfiguration _config;
public DataAccess(IConfiguration config)
{
_config = config;
}
public void Method()
{
var connectionString = _config.GetValue<string>("App:Connection:Value"); //notice the structure of this string
//do whatever with connection string
}
}
Now, in your ASP.net Core web project, you need to 'wire up' your dependency. In Startup.cs, I'm using this (from the default boilerplate template)
public class Startup
{
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)
{
services.AddMvc();
services.AddSingleton<IConfiguration>(Configuration); //add Configuration to our services collection
services.AddTransient<IDataAccess, DataAccess>(); // register our IDataAccess class (from class library)
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseMvc();
}
}
Now, when your code in your class library gets executed, the ctor gets handed the instance of IConfiguration
you have set up in your web app
Note: You can create strongly typed settings class if you'd prefer, see here for more information
Upvotes: 9
Reputation: 9165
I would suggest Options pattern. You can create the class with configuration data, e.g.:
public class ConnectionStringConfig
{
public string ConnectionString { get; set; }
}
Register it on Startup:
public void ConfigureServices(IServiceCollection services)
{
...
services.Configure<ConnectionStringConfig>(Configuration);
}
and inject in your data access layer
private readonly ConnectionStringConfig config;
public Repository(IOptions<ConnectionStringConfig> config)
{
this.config = config.Value;
}
Upvotes: 4