Just starting playing with the .Net Core RC2 by migrating a current MVC .Net app I developed. It looks like to me because of the way that configuration is handled with appsettings.json that if I have multiple connection strings I either have to use EF to retrieve a connectionstring or I have to create separate classes named for each connection string. All the examples I see either use EF (which doesn't make sense for me since I will be using Dapper) or the example builds a class named after the section in the config. Am I missing a better solution?
"Data": {
"Server1": {
"ConnectionString": "data source={server1};initial catalog=master;integrated security=True;"
},
"Server2": {
"ConnectionString": "data source={server2};initial catalog=master;integrated security=True;"
}
}
Why would I want to build two classes, one named "Server1" and another "Server2" if the only property each had was a connectionstring?
There are a couple of corrections that I made to Adem's response to work with RC2, so I figured I better post them.
I configured the appsettings.json and created a class like Adem's
{
"ConnectionStrings": {
"DefaultConnectionString": "Default",
"CustomConnectionString": "Custom"
}
}
and
public class ConnectionStrings
{
public string DefaultConnectionString { get; set; }
public string CustomConnectionString { get; set; }
}
most of Adem's code comes out of the box in VS for RC2, so I just added the line below to the ConfigureServices method
services.Configure<Models.ConnectionStrings>(Configuration.GetSection("ConnectionStrings"));
The main missing point is that the connection string has to be passed to the controller (Once you’ve specified a strongly-typed configuration object and added it to the services collection, you can request it from any Controller or Action method by requesting an instance of IOptions, https://docs.asp.net/en/latest/mvc/controllers/dependency-injection.html)
So this goes to the controller,
private readonly ConnectionStrings _connectionStrings;
public HomeController(IOptions<ConnectionStrings> connectionStrings)
{
_connectionStrings = connectionStrings.Value;
}
and then when you instantiate the DAL you pass the appropriate connectionString
DAL.DataMethods dm = new DAL.DataMethods(_connectionStrings.CustomConnectionString);
All the examples show this, they just don't state it, why my attempts to pull directly from the DAL didn't work
You can use Options
to access in DAL
layer. I will try to write simple example(RC1):
First you need to create appsettings.json file with below content:
{
"ConnectionStrings": {
"DefaultConnectionString": "Default",
"CustomConnectionString": "Custom"
}
}
Then create a class:
public class ConnectionStrings
{
public string DefaultConnectionString { get; set; }
public string CustomConnectionString { get; set; }
}
And in Startup.cs
private IConfiguration Configuration;
public Startup(IApplicationEnvironment app)
{
var builder = new ConfigurationBuilder()
.SetBasePath(app.ApplicationBasePath)
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
// ....
services.AddOptions();
services.Configure<ConnectionStrings>(Configuration.GetSection("ConnectionStrings"));
}
Finally inject it in the DAL
class:
private IOptions<ConnectionStrings> _connectionStrings;
public DalClass(IOptions<ConnectionStrings> connectionStrings)
{
_connectionStrings = connectionStrings;
}
//use it
I don't like the idea of instantiating the DAL. Rather, I'd do something like this
public class ConnectionStrings : Dictionary<string, string> { }
And something like this in the ctor of the DAL
public Dal(IOptionsMonitor<ConnectionStrings> optionsAccessor, ILogger<Dal> logger)
{
_connections = optionsAccessor.CurrentValue;
_logger = logger;
}
Now you have all the connection strings in the DAL object. You can use them on each query or even select it by index on every call.