How to read a connectionString WITH PROVIDER in .NET Core?
I added
.AddJsonFile("Connections.json", optional: true, reloadOnChange: true)
in
public Startup(IHostingEnvironment env)
Connections.json contains:
"ConnectionStrings":
"DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=DATABASE;Trusted_Connection=True;MultipleActiveResultSets=true",
"COR-W81-101": "Data Source=DATASOURCE;Initial Catalog=P61_CAFM_Basic;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"COR-W81-100": "Data Source=DATASOURCE;Initial Catalog=Post_PS;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"MSEDGEWIN10": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"server": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;User Id=USERID;Password=PASSWORD;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic""
,
"conStrings": [
"name": "COR-W81-101",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"name": "server",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
],
"conStringDictionary":
"COR-W81-101":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"server":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
}
Now I wanted to read the connectionStrings:
public class ConnectionString
public string name get; set;
public string connectionString get; set;
public string providerName get; set;
like this:
//Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<ConnectionString>(services, Configuration.GetSection("conStrings"));
// https://stackoverflow.com/questions/31929482/retrieve-sections-from-config-json-in-asp-net-5
//var objectSections = Configuration.GetSection("conStringDictionary").GetChildren();
//foreach (var x in objectSections)
//
// System.Console.WriteLine(x.Key);
// var cs = new ConnectionString();
// ConfigurationBinder.Bind(x, cs);
// System.Console.WriteLine(cs);
//
// http://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<Dictionary<string, ConnectionString>>(services, Configuration.GetSection("conStrings"));
But I can't get it to read the array or the dictionary. I need the providerName for each connectionString, and I want to have it in the same entry as the connection string, but not as a joined string.
c# asp.net-core asp.net-core-mvc .net-core asp.net-core-1.0
add a comment |
I added
.AddJsonFile("Connections.json", optional: true, reloadOnChange: true)
in
public Startup(IHostingEnvironment env)
Connections.json contains:
"ConnectionStrings":
"DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=DATABASE;Trusted_Connection=True;MultipleActiveResultSets=true",
"COR-W81-101": "Data Source=DATASOURCE;Initial Catalog=P61_CAFM_Basic;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"COR-W81-100": "Data Source=DATASOURCE;Initial Catalog=Post_PS;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"MSEDGEWIN10": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"server": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;User Id=USERID;Password=PASSWORD;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic""
,
"conStrings": [
"name": "COR-W81-101",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"name": "server",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
],
"conStringDictionary":
"COR-W81-101":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"server":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
}
Now I wanted to read the connectionStrings:
public class ConnectionString
public string name get; set;
public string connectionString get; set;
public string providerName get; set;
like this:
//Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<ConnectionString>(services, Configuration.GetSection("conStrings"));
// https://stackoverflow.com/questions/31929482/retrieve-sections-from-config-json-in-asp-net-5
//var objectSections = Configuration.GetSection("conStringDictionary").GetChildren();
//foreach (var x in objectSections)
//
// System.Console.WriteLine(x.Key);
// var cs = new ConnectionString();
// ConfigurationBinder.Bind(x, cs);
// System.Console.WriteLine(cs);
//
// http://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<Dictionary<string, ConnectionString>>(services, Configuration.GetSection("conStrings"));
But I can't get it to read the array or the dictionary. I need the providerName for each connectionString, and I want to have it in the same entry as the connection string, but not as a joined string.
c# asp.net-core asp.net-core-mvc .net-core asp.net-core-1.0
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
5
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12
add a comment |
I added
.AddJsonFile("Connections.json", optional: true, reloadOnChange: true)
in
public Startup(IHostingEnvironment env)
Connections.json contains:
"ConnectionStrings":
"DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=DATABASE;Trusted_Connection=True;MultipleActiveResultSets=true",
"COR-W81-101": "Data Source=DATASOURCE;Initial Catalog=P61_CAFM_Basic;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"COR-W81-100": "Data Source=DATASOURCE;Initial Catalog=Post_PS;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"MSEDGEWIN10": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"server": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;User Id=USERID;Password=PASSWORD;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic""
,
"conStrings": [
"name": "COR-W81-101",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"name": "server",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
],
"conStringDictionary":
"COR-W81-101":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"server":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
}
Now I wanted to read the connectionStrings:
public class ConnectionString
public string name get; set;
public string connectionString get; set;
public string providerName get; set;
like this:
//Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<ConnectionString>(services, Configuration.GetSection("conStrings"));
// https://stackoverflow.com/questions/31929482/retrieve-sections-from-config-json-in-asp-net-5
//var objectSections = Configuration.GetSection("conStringDictionary").GetChildren();
//foreach (var x in objectSections)
//
// System.Console.WriteLine(x.Key);
// var cs = new ConnectionString();
// ConfigurationBinder.Bind(x, cs);
// System.Console.WriteLine(cs);
//
// http://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<Dictionary<string, ConnectionString>>(services, Configuration.GetSection("conStrings"));
But I can't get it to read the array or the dictionary. I need the providerName for each connectionString, and I want to have it in the same entry as the connection string, but not as a joined string.
c# asp.net-core asp.net-core-mvc .net-core asp.net-core-1.0
I added
.AddJsonFile("Connections.json", optional: true, reloadOnChange: true)
in
public Startup(IHostingEnvironment env)
Connections.json contains:
"ConnectionStrings":
"DefaultConnection": "Server=(localdb)\mssqllocaldb;Database=DATABASE;Trusted_Connection=True;MultipleActiveResultSets=true",
"COR-W81-101": "Data Source=DATASOURCE;Initial Catalog=P61_CAFM_Basic;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"COR-W81-100": "Data Source=DATASOURCE;Initial Catalog=Post_PS;User Id=USERID;Password=PASSWORD;Persist Security Info=False;MultipleActiveResultSets=False;Packet Size=4096;",
"MSEDGEWIN10": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"server": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;User Id=USERID;Password=PASSWORD;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic""
,
"conStrings": [
"name": "COR-W81-101",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"name": "server",
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
],
"conStringDictionary":
"COR-W81-101":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
,
"server":
"connectionString": "Data Source=DATASOURCE; Initial Catalog=COR_Basic; Persist Security Info=False;Integrated Security=true;MultipleActiveResultSets=False;Packet Size=4096;Application Name="COR_Basic"",
"providerName": "System.Data.SqlClient"
}
Now I wanted to read the connectionStrings:
public class ConnectionString
public string name get; set;
public string connectionString get; set;
public string providerName get; set;
like this:
//Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<ConnectionString>(services, Configuration.GetSection("conStrings"));
// https://stackoverflow.com/questions/31929482/retrieve-sections-from-config-json-in-asp-net-5
//var objectSections = Configuration.GetSection("conStringDictionary").GetChildren();
//foreach (var x in objectSections)
//
// System.Console.WriteLine(x.Key);
// var cs = new ConnectionString();
// ConfigurationBinder.Bind(x, cs);
// System.Console.WriteLine(cs);
//
// http://andrewlock.net/how-to-use-the-ioptions-pattern-for-configuration-in-asp-net-core-rc2/
Microsoft.Extensions.DependencyInjection.OptionsConfigurationServiceCollectionExtensions.Configure<Dictionary<string, ConnectionString>>(services, Configuration.GetSection("conStrings"));
But I can't get it to read the array or the dictionary. I need the providerName for each connectionString, and I want to have it in the same entry as the connection string, but not as a joined string.
c# asp.net-core asp.net-core-mvc .net-core asp.net-core-1.0
c# asp.net-core asp.net-core-mvc .net-core asp.net-core-1.0
edited Nov 28 '16 at 17:11
asked Nov 28 '16 at 13:30
user6038265
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
5
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12
add a comment |
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
5
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
5
5
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12
add a comment |
3 Answers
3
active
oldest
votes
You were basically there, all you have to do is make a few strongly typed classes to match the old ConnectionStringSettings and utilize some collection serialization logic.
Here's how I would suggest to format them in json. Rather similar to how you would specify a connection string the old XML app/web.config way. The name of the connection string being the key.
"ConnectionStrings":
"Test1":
"ConnectionString": "server=localhost;database=db;username=user;password=pass;",
"ProviderName": "MySql.Data.MySqlClient"
,
"Test2":
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "MySql.Data.MySqlClient"
Now for the classes to bind to. First is the simple ConnectionStringSettings class itself, implements your basic equality/hashing methods (will be necessary as we intend to stick this in a Dictionary).
public class ConnectionStringSettings
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringSettings()
public ConnectionStringSettings(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringSettings(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
protected bool Equals(ConnectionStringSettings other)
return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
public override bool Equals(Object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConnectionStringSettings) obj);
public override int GetHashCode()
unchecked
int hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
return hashCode;
public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
return Equals(left, right);
public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
return !Equals(left, right);
Next is the collection of ConnectionStringSettings. This is only necessary because the Name of the connection string is the key in the JSON notation. In order to keep that name consistently attached we need to override Dictionary's Add method (but you can't do that because its not virtual). So all we are REALLY doing is just wrapping a Dictionary internally with that extra bit in our own Add implementation. Again this looks like a lot of code, but you'll see it's very monotonous boring stuff.
public class ConnectionStringSettingsCollection : IDictionary<String, ConnectionStringSettings>
private readonly Dictionary<String, ConnectionStringSettings> m_ConnectionStrings;
public ConnectionStringSettingsCollection()
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>();
public ConnectionStringSettingsCollection(int capacity)
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>(capacity);
#region IEnumerable methods
IEnumerator IEnumerable.GetEnumerator()
return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
#endregion
#region IEnumerable<> methods
IEnumerator<KeyValuePair<String, ConnectionStringSettings>> IEnumerable<KeyValuePair<String, ConnectionStringSettings>>.GetEnumerator()
return ((IEnumerable<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).GetEnumerator();
#endregion
#region ICollection<> methods
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Add(KeyValuePair<String, ConnectionStringSettings> item)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Add(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Clear()
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Clear();
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Contains(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Contains(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.CopyTo(KeyValuePair<String, ConnectionStringSettings> array, Int32 arrayIndex)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).CopyTo(array, arrayIndex);
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Remove(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Remove(item);
public Int32 Count => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Count;
public Boolean IsReadOnly => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).IsReadOnly;
#endregion
#region IDictionary<> methods
public void Add(String key, ConnectionStringSettings value)
// NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
value.Name = key;
m_ConnectionStrings.Add(key, value);
public Boolean ContainsKey(String key)
return m_ConnectionStrings.ContainsKey(key);
public Boolean Remove(String key)
return m_ConnectionStrings.Remove(key);
public Boolean TryGetValue(String key, out ConnectionStringSettings value)
return m_ConnectionStrings.TryGetValue(key, out value);
public ConnectionStringSettings this[String key]
get => m_ConnectionStrings[key];
set => Add(key, value);
public ICollection<String> Keys => m_ConnectionStrings.Keys;
public ICollection<ConnectionStringSettings> Values => m_ConnectionStrings.Values;
#endregion
A few simple extension methods to make things simpler.
public static class ConnectionStringSettingsExtensions
public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null)
return new ConnectionStringSettingsCollection();
return connectionStringCollection;
public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
ConnectionStringSettings connectionStringSettings;
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null
Finally the usage.
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
var connectionStrings = configuration.ConnectionStrings();
foreach (var connectionString in connectionStrings.Values)
Console.WriteLine(connectionString.Name);
Console.WriteLine(connectionString.ConnectionString);
Console.WriteLine(connectionString.ProviderName);
var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);
var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
add a comment |
First off, Nicholi's answer inspired me! Thanks Nicholi.
Second, I have a "List" solution rather than a IDictionary solution. It's not as smooth as the IDictionary solution.
This can also be dubbed "how to create a collection list for dot net core configuration"
Here we go:
first a shameless theft!
public class ConnectionStringEntry
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringEntry()
public ConnectionStringEntry(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringEntry(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
second, a "wrapper". I wanted to track a DefaultConnectionStringName...along side my List (collection) of Entries.
public class ConnectionStringWrapper
public string DefaultConnectionStringName get; set; = "";
public List<ConnectionStringEntry> ConnectionStringEntries get; set; = new List<ConnectionStringEntry>();
//public Dictionary<string, ConnectionStringEntry> ConnectionStringEntries get; set; = new Dictionary<string, ConnectionStringEntry>();
public ConnectionStringEntry GetDefaultConnectionStringEntry()
ConnectionStringEntry returnItem = this.GetConnectionStringEntry(this.DefaultConnectionStringName);
return returnItem;
public ConnectionStringEntry GetConnectionStringEntry(string name)
ConnectionStringEntry returnItem = null;
if (null != this.ConnectionStringEntries && this.ConnectionStringEntries.Any())
returnItem = this.ConnectionStringEntries.FirstOrDefault(ce => ce.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (null == returnItem)
throw new ArgumentOutOfRangeException(string.Format("No default ConnectionStringEntry found. (ConnectionStringEntries.Names='0', Search.Name='1')", this.ConnectionStringEntries == null ? string.Empty : string.Join(",", this.ConnectionStringEntries.Select(ce => ce.Name)), name));
return returnItem;
Now, my reading the json and mapping to a concrete settings object code:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConnectionStringWrapper settings = new ConnectionStringWrapper();
config.Bind("ConnectionStringWrapperSettings", settings);
Console.WriteLine("0, 1", settings.DefaultConnectionStringName, settings.ConnectionStringEntries.Count);
ConnectionStringEntry cse = settings.GetDefaultConnectionStringEntry();
My nuget packages:
.nugetpackagesmicrosoft.extensions.configuration2.1.1
.nugetpackagesmicrosoft.extensions.configuration.binder2.1.1
.nugetpackagesmicrosoft.extensions.configuration.json2.1.1
BONUS MATERIAL BELOW:
One of the things I am (trying) to so support a code base that can be deployed as DotNet 4.x ("classic" ?? as the term now??) and dotnet core.
To that end, I've written the above to provide an abstraction from the way DotNet(Classic) handles connection strings (xml, our old long time friend) and now the new cool kid on the block : DotNetCore with json.
To that end, I've written an interface:
public interface IConnectionStringWrapperRetriever
ConnectionStringWrapper RetrieveConnectionStringWrapper();
and I have an implementation for dotnetcore:
public class ConnectionStringWrapperDotNetCoreRetriever : IConnectionStringWrapperRetriever
public const string ConnectionStringWrapperSettingsJsonElementName = "ConnectionStringWrapperSettings";
private readonly IConfiguration config;
public ConnectionStringWrapperDotNetCoreRetriever(IConfiguration cnfg)
this.config = cnfg;
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper settings = new ConnectionStringWrapper();
this.config.Bind(ConnectionStringWrapperSettingsJsonElementName, settings);
return settings;
Oh yeah, the all important JSON setup:
"ConnectionStringWrapperSettings":
"DefaultConnectionStringName": "abc",
"ConnectionStringEntries": [
"Name": "abc",
"ConnectionString": "Server=myserver;Database=mydatabase;Trusted_Connection=True;MultipleActiveResultSets=true",
"ProviderName": "SomeProvider"
,
"Name": "def",
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "SomeProvider"
]
.............
For DotNet(classic), all you need to do is implement a second concrete for IConnectionStringWrapperRetriever, and do the magic.
Remember the below xml? (ha ha, its not that old yet!)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
(from https://docs.microsoft.com/en-us/dotnet/api/system.configuration.connectionstringsettingscollection?view=netframework-4.7.2)
Remember this stuff from EnterpriseLibrary?
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase="ConnStr1"/>
I'll leave the DotNet(Classic) implementation to the reader.
But now I inject IConnectionStringWrapperRetriever into my DataLayer classes.
I'm using Dapper, so I can fish a connection string using IConnectionStringWrapperRetriever.
If my project is "house" DotNet(Classic), I inject one version of IConnectionStringWrapperRetriever (not seen here, left to the reader). If my project is "housed" in DotNetCore I inject a second (shown above) version of IConnectionStringWrapperRetriever.
Outside the scope of this post, but by "housed", I mean I have 2 csproj's sitting side by side.
MyApp.DataLayer.classic.csproj
and
MyApp.DataLayer.csproj
I find it easier to leave the default csproj to house the DotNetCore stuff. And I use the "classic.csproj" file to house the DotNet(classic). My assembly name and default namespace remain "MyApp.Datalayer"......the .classic is ONLY for the csrproj filename to distinquish.
I create two solution sln files too. MySolution.classic.sln and MySolution.sln.
It seems to be working.....with this ConnectionString abstraction I wrote above.
The ONLY conditional I have is on the (classic) AssemblyInfo.cs files.
#if(!NETCOREAPP2_1)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/* all the other stuff removed here */
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
APPEND:
Ok, here is the DotNet(Classic) version:
public class ConnectionStringWrapperDotNetClassicRetriever : IConnectionStringWrapperRetriever
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper returnItem = new ConnectionStringWrapper();
foreach(ConnectionStringSettings css in System.Configuration.ConfigurationManager.ConnectionStrings)
ConnectionStringEntry cse = new ConnectionStringEntry(css.Name, css.ConnectionString, css.ProviderName);
returnItem.ConnectionStringEntries.Add(cse);
if(returnItem.ConnectionStringEntries.Count == 1)
/* if there is only one, set the default name to that one */
returnItem.DefaultConnectionStringName = returnItem.ConnectionStringEntries.First().Name;
else
/*
<packages>
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
<package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
</packages>
*/
/* using Microsoft.Practices.EnterpriseLibrary.Data.Configuration; */
/* You can write you own way to handle a default database, or piggyback off of EnterpriseLibrary. You don't necessarily have to use EnterpriseLibrary.Data, you are simply piggybacking on their xml/configuration setup */
DatabaseSettings dbSettings = (DatabaseSettings)ConfigurationManager.GetSection("dataConfiguration");
returnItem.DefaultConnectionStringName = dbSettings.DefaultDatabase;
return returnItem;
And the app.config xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
<connectionStrings>
<clear/>
<add name="MyFirstConnectionStringName" connectionString="Server=.MyServerOne;Database=OneDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
<add name="MySecondConnectionStringName" connectionString="Server=.MyServerTwo;Database=TwoDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<dataConfiguration defaultDatabase="MyFirstConnectionStringName" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Key words:
DotNet DotNet .Net Core Classic Json Configuration ICollection scalar and collection support both dotnet and dotnetcore
add a comment |
Something like:
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
var conString = configurationRoot["ConnectionStrings:MyConnection"]);
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40845542%2fhow-to-read-a-connectionstring-with-provider-in-net-core%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
You were basically there, all you have to do is make a few strongly typed classes to match the old ConnectionStringSettings and utilize some collection serialization logic.
Here's how I would suggest to format them in json. Rather similar to how you would specify a connection string the old XML app/web.config way. The name of the connection string being the key.
"ConnectionStrings":
"Test1":
"ConnectionString": "server=localhost;database=db;username=user;password=pass;",
"ProviderName": "MySql.Data.MySqlClient"
,
"Test2":
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "MySql.Data.MySqlClient"
Now for the classes to bind to. First is the simple ConnectionStringSettings class itself, implements your basic equality/hashing methods (will be necessary as we intend to stick this in a Dictionary).
public class ConnectionStringSettings
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringSettings()
public ConnectionStringSettings(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringSettings(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
protected bool Equals(ConnectionStringSettings other)
return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
public override bool Equals(Object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConnectionStringSettings) obj);
public override int GetHashCode()
unchecked
int hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
return hashCode;
public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
return Equals(left, right);
public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
return !Equals(left, right);
Next is the collection of ConnectionStringSettings. This is only necessary because the Name of the connection string is the key in the JSON notation. In order to keep that name consistently attached we need to override Dictionary's Add method (but you can't do that because its not virtual). So all we are REALLY doing is just wrapping a Dictionary internally with that extra bit in our own Add implementation. Again this looks like a lot of code, but you'll see it's very monotonous boring stuff.
public class ConnectionStringSettingsCollection : IDictionary<String, ConnectionStringSettings>
private readonly Dictionary<String, ConnectionStringSettings> m_ConnectionStrings;
public ConnectionStringSettingsCollection()
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>();
public ConnectionStringSettingsCollection(int capacity)
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>(capacity);
#region IEnumerable methods
IEnumerator IEnumerable.GetEnumerator()
return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
#endregion
#region IEnumerable<> methods
IEnumerator<KeyValuePair<String, ConnectionStringSettings>> IEnumerable<KeyValuePair<String, ConnectionStringSettings>>.GetEnumerator()
return ((IEnumerable<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).GetEnumerator();
#endregion
#region ICollection<> methods
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Add(KeyValuePair<String, ConnectionStringSettings> item)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Add(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Clear()
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Clear();
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Contains(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Contains(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.CopyTo(KeyValuePair<String, ConnectionStringSettings> array, Int32 arrayIndex)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).CopyTo(array, arrayIndex);
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Remove(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Remove(item);
public Int32 Count => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Count;
public Boolean IsReadOnly => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).IsReadOnly;
#endregion
#region IDictionary<> methods
public void Add(String key, ConnectionStringSettings value)
// NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
value.Name = key;
m_ConnectionStrings.Add(key, value);
public Boolean ContainsKey(String key)
return m_ConnectionStrings.ContainsKey(key);
public Boolean Remove(String key)
return m_ConnectionStrings.Remove(key);
public Boolean TryGetValue(String key, out ConnectionStringSettings value)
return m_ConnectionStrings.TryGetValue(key, out value);
public ConnectionStringSettings this[String key]
get => m_ConnectionStrings[key];
set => Add(key, value);
public ICollection<String> Keys => m_ConnectionStrings.Keys;
public ICollection<ConnectionStringSettings> Values => m_ConnectionStrings.Values;
#endregion
A few simple extension methods to make things simpler.
public static class ConnectionStringSettingsExtensions
public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null)
return new ConnectionStringSettingsCollection();
return connectionStringCollection;
public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
ConnectionStringSettings connectionStringSettings;
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null
Finally the usage.
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
var connectionStrings = configuration.ConnectionStrings();
foreach (var connectionString in connectionStrings.Values)
Console.WriteLine(connectionString.Name);
Console.WriteLine(connectionString.ConnectionString);
Console.WriteLine(connectionString.ProviderName);
var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);
var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
add a comment |
You were basically there, all you have to do is make a few strongly typed classes to match the old ConnectionStringSettings and utilize some collection serialization logic.
Here's how I would suggest to format them in json. Rather similar to how you would specify a connection string the old XML app/web.config way. The name of the connection string being the key.
"ConnectionStrings":
"Test1":
"ConnectionString": "server=localhost;database=db;username=user;password=pass;",
"ProviderName": "MySql.Data.MySqlClient"
,
"Test2":
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "MySql.Data.MySqlClient"
Now for the classes to bind to. First is the simple ConnectionStringSettings class itself, implements your basic equality/hashing methods (will be necessary as we intend to stick this in a Dictionary).
public class ConnectionStringSettings
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringSettings()
public ConnectionStringSettings(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringSettings(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
protected bool Equals(ConnectionStringSettings other)
return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
public override bool Equals(Object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConnectionStringSettings) obj);
public override int GetHashCode()
unchecked
int hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
return hashCode;
public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
return Equals(left, right);
public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
return !Equals(left, right);
Next is the collection of ConnectionStringSettings. This is only necessary because the Name of the connection string is the key in the JSON notation. In order to keep that name consistently attached we need to override Dictionary's Add method (but you can't do that because its not virtual). So all we are REALLY doing is just wrapping a Dictionary internally with that extra bit in our own Add implementation. Again this looks like a lot of code, but you'll see it's very monotonous boring stuff.
public class ConnectionStringSettingsCollection : IDictionary<String, ConnectionStringSettings>
private readonly Dictionary<String, ConnectionStringSettings> m_ConnectionStrings;
public ConnectionStringSettingsCollection()
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>();
public ConnectionStringSettingsCollection(int capacity)
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>(capacity);
#region IEnumerable methods
IEnumerator IEnumerable.GetEnumerator()
return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
#endregion
#region IEnumerable<> methods
IEnumerator<KeyValuePair<String, ConnectionStringSettings>> IEnumerable<KeyValuePair<String, ConnectionStringSettings>>.GetEnumerator()
return ((IEnumerable<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).GetEnumerator();
#endregion
#region ICollection<> methods
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Add(KeyValuePair<String, ConnectionStringSettings> item)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Add(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Clear()
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Clear();
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Contains(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Contains(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.CopyTo(KeyValuePair<String, ConnectionStringSettings> array, Int32 arrayIndex)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).CopyTo(array, arrayIndex);
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Remove(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Remove(item);
public Int32 Count => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Count;
public Boolean IsReadOnly => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).IsReadOnly;
#endregion
#region IDictionary<> methods
public void Add(String key, ConnectionStringSettings value)
// NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
value.Name = key;
m_ConnectionStrings.Add(key, value);
public Boolean ContainsKey(String key)
return m_ConnectionStrings.ContainsKey(key);
public Boolean Remove(String key)
return m_ConnectionStrings.Remove(key);
public Boolean TryGetValue(String key, out ConnectionStringSettings value)
return m_ConnectionStrings.TryGetValue(key, out value);
public ConnectionStringSettings this[String key]
get => m_ConnectionStrings[key];
set => Add(key, value);
public ICollection<String> Keys => m_ConnectionStrings.Keys;
public ICollection<ConnectionStringSettings> Values => m_ConnectionStrings.Values;
#endregion
A few simple extension methods to make things simpler.
public static class ConnectionStringSettingsExtensions
public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null)
return new ConnectionStringSettingsCollection();
return connectionStringCollection;
public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
ConnectionStringSettings connectionStringSettings;
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null
Finally the usage.
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
var connectionStrings = configuration.ConnectionStrings();
foreach (var connectionString in connectionStrings.Values)
Console.WriteLine(connectionString.Name);
Console.WriteLine(connectionString.ConnectionString);
Console.WriteLine(connectionString.ProviderName);
var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);
var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
add a comment |
You were basically there, all you have to do is make a few strongly typed classes to match the old ConnectionStringSettings and utilize some collection serialization logic.
Here's how I would suggest to format them in json. Rather similar to how you would specify a connection string the old XML app/web.config way. The name of the connection string being the key.
"ConnectionStrings":
"Test1":
"ConnectionString": "server=localhost;database=db;username=user;password=pass;",
"ProviderName": "MySql.Data.MySqlClient"
,
"Test2":
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "MySql.Data.MySqlClient"
Now for the classes to bind to. First is the simple ConnectionStringSettings class itself, implements your basic equality/hashing methods (will be necessary as we intend to stick this in a Dictionary).
public class ConnectionStringSettings
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringSettings()
public ConnectionStringSettings(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringSettings(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
protected bool Equals(ConnectionStringSettings other)
return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
public override bool Equals(Object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConnectionStringSettings) obj);
public override int GetHashCode()
unchecked
int hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
return hashCode;
public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
return Equals(left, right);
public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
return !Equals(left, right);
Next is the collection of ConnectionStringSettings. This is only necessary because the Name of the connection string is the key in the JSON notation. In order to keep that name consistently attached we need to override Dictionary's Add method (but you can't do that because its not virtual). So all we are REALLY doing is just wrapping a Dictionary internally with that extra bit in our own Add implementation. Again this looks like a lot of code, but you'll see it's very monotonous boring stuff.
public class ConnectionStringSettingsCollection : IDictionary<String, ConnectionStringSettings>
private readonly Dictionary<String, ConnectionStringSettings> m_ConnectionStrings;
public ConnectionStringSettingsCollection()
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>();
public ConnectionStringSettingsCollection(int capacity)
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>(capacity);
#region IEnumerable methods
IEnumerator IEnumerable.GetEnumerator()
return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
#endregion
#region IEnumerable<> methods
IEnumerator<KeyValuePair<String, ConnectionStringSettings>> IEnumerable<KeyValuePair<String, ConnectionStringSettings>>.GetEnumerator()
return ((IEnumerable<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).GetEnumerator();
#endregion
#region ICollection<> methods
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Add(KeyValuePair<String, ConnectionStringSettings> item)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Add(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Clear()
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Clear();
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Contains(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Contains(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.CopyTo(KeyValuePair<String, ConnectionStringSettings> array, Int32 arrayIndex)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).CopyTo(array, arrayIndex);
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Remove(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Remove(item);
public Int32 Count => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Count;
public Boolean IsReadOnly => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).IsReadOnly;
#endregion
#region IDictionary<> methods
public void Add(String key, ConnectionStringSettings value)
// NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
value.Name = key;
m_ConnectionStrings.Add(key, value);
public Boolean ContainsKey(String key)
return m_ConnectionStrings.ContainsKey(key);
public Boolean Remove(String key)
return m_ConnectionStrings.Remove(key);
public Boolean TryGetValue(String key, out ConnectionStringSettings value)
return m_ConnectionStrings.TryGetValue(key, out value);
public ConnectionStringSettings this[String key]
get => m_ConnectionStrings[key];
set => Add(key, value);
public ICollection<String> Keys => m_ConnectionStrings.Keys;
public ICollection<ConnectionStringSettings> Values => m_ConnectionStrings.Values;
#endregion
A few simple extension methods to make things simpler.
public static class ConnectionStringSettingsExtensions
public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null)
return new ConnectionStringSettingsCollection();
return connectionStringCollection;
public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
ConnectionStringSettings connectionStringSettings;
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null
Finally the usage.
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
var connectionStrings = configuration.ConnectionStrings();
foreach (var connectionString in connectionStrings.Values)
Console.WriteLine(connectionString.Name);
Console.WriteLine(connectionString.ConnectionString);
Console.WriteLine(connectionString.ProviderName);
var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);
var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);
You were basically there, all you have to do is make a few strongly typed classes to match the old ConnectionStringSettings and utilize some collection serialization logic.
Here's how I would suggest to format them in json. Rather similar to how you would specify a connection string the old XML app/web.config way. The name of the connection string being the key.
"ConnectionStrings":
"Test1":
"ConnectionString": "server=localhost;database=db;username=user;password=pass;",
"ProviderName": "MySql.Data.MySqlClient"
,
"Test2":
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "MySql.Data.MySqlClient"
Now for the classes to bind to. First is the simple ConnectionStringSettings class itself, implements your basic equality/hashing methods (will be necessary as we intend to stick this in a Dictionary).
public class ConnectionStringSettings
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringSettings()
public ConnectionStringSettings(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringSettings(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
protected bool Equals(ConnectionStringSettings other)
return String.Equals(Name, other.Name) && String.Equals(ConnectionString, other.ConnectionString) && String.Equals(ProviderName, other.ProviderName);
public override bool Equals(Object obj)
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
if (obj.GetType() != this.GetType()) return false;
return Equals((ConnectionStringSettings) obj);
public override int GetHashCode()
unchecked
int hashCode = (Name != null ? Name.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ConnectionString != null ? ConnectionString.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (ProviderName != null ? ProviderName.GetHashCode() : 0);
return hashCode;
public static bool operator ==(ConnectionStringSettings left, ConnectionStringSettings right)
return Equals(left, right);
public static bool operator !=(ConnectionStringSettings left, ConnectionStringSettings right)
return !Equals(left, right);
Next is the collection of ConnectionStringSettings. This is only necessary because the Name of the connection string is the key in the JSON notation. In order to keep that name consistently attached we need to override Dictionary's Add method (but you can't do that because its not virtual). So all we are REALLY doing is just wrapping a Dictionary internally with that extra bit in our own Add implementation. Again this looks like a lot of code, but you'll see it's very monotonous boring stuff.
public class ConnectionStringSettingsCollection : IDictionary<String, ConnectionStringSettings>
private readonly Dictionary<String, ConnectionStringSettings> m_ConnectionStrings;
public ConnectionStringSettingsCollection()
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>();
public ConnectionStringSettingsCollection(int capacity)
m_ConnectionStrings = new Dictionary<String, ConnectionStringSettings>(capacity);
#region IEnumerable methods
IEnumerator IEnumerable.GetEnumerator()
return ((IEnumerable)m_ConnectionStrings).GetEnumerator();
#endregion
#region IEnumerable<> methods
IEnumerator<KeyValuePair<String, ConnectionStringSettings>> IEnumerable<KeyValuePair<String, ConnectionStringSettings>>.GetEnumerator()
return ((IEnumerable<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).GetEnumerator();
#endregion
#region ICollection<> methods
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Add(KeyValuePair<String, ConnectionStringSettings> item)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Add(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.Clear()
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Clear();
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Contains(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Contains(item);
void ICollection<KeyValuePair<String, ConnectionStringSettings>>.CopyTo(KeyValuePair<String, ConnectionStringSettings> array, Int32 arrayIndex)
((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).CopyTo(array, arrayIndex);
Boolean ICollection<KeyValuePair<String, ConnectionStringSettings>>.Remove(KeyValuePair<String, ConnectionStringSettings> item)
return ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Remove(item);
public Int32 Count => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).Count;
public Boolean IsReadOnly => ((ICollection<KeyValuePair<String, ConnectionStringSettings>>)m_ConnectionStrings).IsReadOnly;
#endregion
#region IDictionary<> methods
public void Add(String key, ConnectionStringSettings value)
// NOTE only slight modification, we add back in the Name of connectionString here (since it is the key)
value.Name = key;
m_ConnectionStrings.Add(key, value);
public Boolean ContainsKey(String key)
return m_ConnectionStrings.ContainsKey(key);
public Boolean Remove(String key)
return m_ConnectionStrings.Remove(key);
public Boolean TryGetValue(String key, out ConnectionStringSettings value)
return m_ConnectionStrings.TryGetValue(key, out value);
public ConnectionStringSettings this[String key]
get => m_ConnectionStrings[key];
set => Add(key, value);
public ICollection<String> Keys => m_ConnectionStrings.Keys;
public ICollection<ConnectionStringSettings> Values => m_ConnectionStrings.Values;
#endregion
A few simple extension methods to make things simpler.
public static class ConnectionStringSettingsExtensions
public static ConnectionStringSettingsCollection ConnectionStrings(this IConfigurationRoot configuration, String section = "ConnectionStrings")
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null)
return new ConnectionStringSettingsCollection();
return connectionStringCollection;
public static ConnectionStringSettings ConnectionString(this IConfigurationRoot configuration, String name, String section = "ConnectionStrings")
ConnectionStringSettings connectionStringSettings;
var connectionStringCollection = configuration.GetSection(section).Get<ConnectionStringSettingsCollection>();
if (connectionStringCollection == null
Finally the usage.
var configuration = new ConfigurationBuilder()
.AddJsonFile("config.json")
.Build();
var connectionStrings = configuration.ConnectionStrings();
foreach (var connectionString in connectionStrings.Values)
Console.WriteLine(connectionString.Name);
Console.WriteLine(connectionString.ConnectionString);
Console.WriteLine(connectionString.ProviderName);
var specificConnStr1 = connectionStrings["Test1"];
Console.WriteLine(specificConnStr1.Name);
Console.WriteLine(specificConnStr1.ConnectionString);
Console.WriteLine(specificConnStr1.ProviderName);
var specificConnStr2 = configuration.ConnectionString("Test2");
Console.WriteLine(specificConnStr2.Name);
Console.WriteLine(specificConnStr2.ConnectionString);
Console.WriteLine(specificConnStr2.ProviderName);
edited May 2 '17 at 2:21
answered Apr 27 '17 at 2:46
NicholiNicholi
8331630
8331630
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
add a comment |
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
Upvote for the inspiration!
– granadaCoder
Nov 15 '18 at 20:25
add a comment |
First off, Nicholi's answer inspired me! Thanks Nicholi.
Second, I have a "List" solution rather than a IDictionary solution. It's not as smooth as the IDictionary solution.
This can also be dubbed "how to create a collection list for dot net core configuration"
Here we go:
first a shameless theft!
public class ConnectionStringEntry
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringEntry()
public ConnectionStringEntry(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringEntry(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
second, a "wrapper". I wanted to track a DefaultConnectionStringName...along side my List (collection) of Entries.
public class ConnectionStringWrapper
public string DefaultConnectionStringName get; set; = "";
public List<ConnectionStringEntry> ConnectionStringEntries get; set; = new List<ConnectionStringEntry>();
//public Dictionary<string, ConnectionStringEntry> ConnectionStringEntries get; set; = new Dictionary<string, ConnectionStringEntry>();
public ConnectionStringEntry GetDefaultConnectionStringEntry()
ConnectionStringEntry returnItem = this.GetConnectionStringEntry(this.DefaultConnectionStringName);
return returnItem;
public ConnectionStringEntry GetConnectionStringEntry(string name)
ConnectionStringEntry returnItem = null;
if (null != this.ConnectionStringEntries && this.ConnectionStringEntries.Any())
returnItem = this.ConnectionStringEntries.FirstOrDefault(ce => ce.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (null == returnItem)
throw new ArgumentOutOfRangeException(string.Format("No default ConnectionStringEntry found. (ConnectionStringEntries.Names='0', Search.Name='1')", this.ConnectionStringEntries == null ? string.Empty : string.Join(",", this.ConnectionStringEntries.Select(ce => ce.Name)), name));
return returnItem;
Now, my reading the json and mapping to a concrete settings object code:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConnectionStringWrapper settings = new ConnectionStringWrapper();
config.Bind("ConnectionStringWrapperSettings", settings);
Console.WriteLine("0, 1", settings.DefaultConnectionStringName, settings.ConnectionStringEntries.Count);
ConnectionStringEntry cse = settings.GetDefaultConnectionStringEntry();
My nuget packages:
.nugetpackagesmicrosoft.extensions.configuration2.1.1
.nugetpackagesmicrosoft.extensions.configuration.binder2.1.1
.nugetpackagesmicrosoft.extensions.configuration.json2.1.1
BONUS MATERIAL BELOW:
One of the things I am (trying) to so support a code base that can be deployed as DotNet 4.x ("classic" ?? as the term now??) and dotnet core.
To that end, I've written the above to provide an abstraction from the way DotNet(Classic) handles connection strings (xml, our old long time friend) and now the new cool kid on the block : DotNetCore with json.
To that end, I've written an interface:
public interface IConnectionStringWrapperRetriever
ConnectionStringWrapper RetrieveConnectionStringWrapper();
and I have an implementation for dotnetcore:
public class ConnectionStringWrapperDotNetCoreRetriever : IConnectionStringWrapperRetriever
public const string ConnectionStringWrapperSettingsJsonElementName = "ConnectionStringWrapperSettings";
private readonly IConfiguration config;
public ConnectionStringWrapperDotNetCoreRetriever(IConfiguration cnfg)
this.config = cnfg;
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper settings = new ConnectionStringWrapper();
this.config.Bind(ConnectionStringWrapperSettingsJsonElementName, settings);
return settings;
Oh yeah, the all important JSON setup:
"ConnectionStringWrapperSettings":
"DefaultConnectionStringName": "abc",
"ConnectionStringEntries": [
"Name": "abc",
"ConnectionString": "Server=myserver;Database=mydatabase;Trusted_Connection=True;MultipleActiveResultSets=true",
"ProviderName": "SomeProvider"
,
"Name": "def",
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "SomeProvider"
]
.............
For DotNet(classic), all you need to do is implement a second concrete for IConnectionStringWrapperRetriever, and do the magic.
Remember the below xml? (ha ha, its not that old yet!)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
(from https://docs.microsoft.com/en-us/dotnet/api/system.configuration.connectionstringsettingscollection?view=netframework-4.7.2)
Remember this stuff from EnterpriseLibrary?
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase="ConnStr1"/>
I'll leave the DotNet(Classic) implementation to the reader.
But now I inject IConnectionStringWrapperRetriever into my DataLayer classes.
I'm using Dapper, so I can fish a connection string using IConnectionStringWrapperRetriever.
If my project is "house" DotNet(Classic), I inject one version of IConnectionStringWrapperRetriever (not seen here, left to the reader). If my project is "housed" in DotNetCore I inject a second (shown above) version of IConnectionStringWrapperRetriever.
Outside the scope of this post, but by "housed", I mean I have 2 csproj's sitting side by side.
MyApp.DataLayer.classic.csproj
and
MyApp.DataLayer.csproj
I find it easier to leave the default csproj to house the DotNetCore stuff. And I use the "classic.csproj" file to house the DotNet(classic). My assembly name and default namespace remain "MyApp.Datalayer"......the .classic is ONLY for the csrproj filename to distinquish.
I create two solution sln files too. MySolution.classic.sln and MySolution.sln.
It seems to be working.....with this ConnectionString abstraction I wrote above.
The ONLY conditional I have is on the (classic) AssemblyInfo.cs files.
#if(!NETCOREAPP2_1)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/* all the other stuff removed here */
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
APPEND:
Ok, here is the DotNet(Classic) version:
public class ConnectionStringWrapperDotNetClassicRetriever : IConnectionStringWrapperRetriever
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper returnItem = new ConnectionStringWrapper();
foreach(ConnectionStringSettings css in System.Configuration.ConfigurationManager.ConnectionStrings)
ConnectionStringEntry cse = new ConnectionStringEntry(css.Name, css.ConnectionString, css.ProviderName);
returnItem.ConnectionStringEntries.Add(cse);
if(returnItem.ConnectionStringEntries.Count == 1)
/* if there is only one, set the default name to that one */
returnItem.DefaultConnectionStringName = returnItem.ConnectionStringEntries.First().Name;
else
/*
<packages>
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
<package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
</packages>
*/
/* using Microsoft.Practices.EnterpriseLibrary.Data.Configuration; */
/* You can write you own way to handle a default database, or piggyback off of EnterpriseLibrary. You don't necessarily have to use EnterpriseLibrary.Data, you are simply piggybacking on their xml/configuration setup */
DatabaseSettings dbSettings = (DatabaseSettings)ConfigurationManager.GetSection("dataConfiguration");
returnItem.DefaultConnectionStringName = dbSettings.DefaultDatabase;
return returnItem;
And the app.config xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
<connectionStrings>
<clear/>
<add name="MyFirstConnectionStringName" connectionString="Server=.MyServerOne;Database=OneDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
<add name="MySecondConnectionStringName" connectionString="Server=.MyServerTwo;Database=TwoDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<dataConfiguration defaultDatabase="MyFirstConnectionStringName" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Key words:
DotNet DotNet .Net Core Classic Json Configuration ICollection scalar and collection support both dotnet and dotnetcore
add a comment |
First off, Nicholi's answer inspired me! Thanks Nicholi.
Second, I have a "List" solution rather than a IDictionary solution. It's not as smooth as the IDictionary solution.
This can also be dubbed "how to create a collection list for dot net core configuration"
Here we go:
first a shameless theft!
public class ConnectionStringEntry
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringEntry()
public ConnectionStringEntry(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringEntry(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
second, a "wrapper". I wanted to track a DefaultConnectionStringName...along side my List (collection) of Entries.
public class ConnectionStringWrapper
public string DefaultConnectionStringName get; set; = "";
public List<ConnectionStringEntry> ConnectionStringEntries get; set; = new List<ConnectionStringEntry>();
//public Dictionary<string, ConnectionStringEntry> ConnectionStringEntries get; set; = new Dictionary<string, ConnectionStringEntry>();
public ConnectionStringEntry GetDefaultConnectionStringEntry()
ConnectionStringEntry returnItem = this.GetConnectionStringEntry(this.DefaultConnectionStringName);
return returnItem;
public ConnectionStringEntry GetConnectionStringEntry(string name)
ConnectionStringEntry returnItem = null;
if (null != this.ConnectionStringEntries && this.ConnectionStringEntries.Any())
returnItem = this.ConnectionStringEntries.FirstOrDefault(ce => ce.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (null == returnItem)
throw new ArgumentOutOfRangeException(string.Format("No default ConnectionStringEntry found. (ConnectionStringEntries.Names='0', Search.Name='1')", this.ConnectionStringEntries == null ? string.Empty : string.Join(",", this.ConnectionStringEntries.Select(ce => ce.Name)), name));
return returnItem;
Now, my reading the json and mapping to a concrete settings object code:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConnectionStringWrapper settings = new ConnectionStringWrapper();
config.Bind("ConnectionStringWrapperSettings", settings);
Console.WriteLine("0, 1", settings.DefaultConnectionStringName, settings.ConnectionStringEntries.Count);
ConnectionStringEntry cse = settings.GetDefaultConnectionStringEntry();
My nuget packages:
.nugetpackagesmicrosoft.extensions.configuration2.1.1
.nugetpackagesmicrosoft.extensions.configuration.binder2.1.1
.nugetpackagesmicrosoft.extensions.configuration.json2.1.1
BONUS MATERIAL BELOW:
One of the things I am (trying) to so support a code base that can be deployed as DotNet 4.x ("classic" ?? as the term now??) and dotnet core.
To that end, I've written the above to provide an abstraction from the way DotNet(Classic) handles connection strings (xml, our old long time friend) and now the new cool kid on the block : DotNetCore with json.
To that end, I've written an interface:
public interface IConnectionStringWrapperRetriever
ConnectionStringWrapper RetrieveConnectionStringWrapper();
and I have an implementation for dotnetcore:
public class ConnectionStringWrapperDotNetCoreRetriever : IConnectionStringWrapperRetriever
public const string ConnectionStringWrapperSettingsJsonElementName = "ConnectionStringWrapperSettings";
private readonly IConfiguration config;
public ConnectionStringWrapperDotNetCoreRetriever(IConfiguration cnfg)
this.config = cnfg;
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper settings = new ConnectionStringWrapper();
this.config.Bind(ConnectionStringWrapperSettingsJsonElementName, settings);
return settings;
Oh yeah, the all important JSON setup:
"ConnectionStringWrapperSettings":
"DefaultConnectionStringName": "abc",
"ConnectionStringEntries": [
"Name": "abc",
"ConnectionString": "Server=myserver;Database=mydatabase;Trusted_Connection=True;MultipleActiveResultSets=true",
"ProviderName": "SomeProvider"
,
"Name": "def",
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "SomeProvider"
]
.............
For DotNet(classic), all you need to do is implement a second concrete for IConnectionStringWrapperRetriever, and do the magic.
Remember the below xml? (ha ha, its not that old yet!)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
(from https://docs.microsoft.com/en-us/dotnet/api/system.configuration.connectionstringsettingscollection?view=netframework-4.7.2)
Remember this stuff from EnterpriseLibrary?
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase="ConnStr1"/>
I'll leave the DotNet(Classic) implementation to the reader.
But now I inject IConnectionStringWrapperRetriever into my DataLayer classes.
I'm using Dapper, so I can fish a connection string using IConnectionStringWrapperRetriever.
If my project is "house" DotNet(Classic), I inject one version of IConnectionStringWrapperRetriever (not seen here, left to the reader). If my project is "housed" in DotNetCore I inject a second (shown above) version of IConnectionStringWrapperRetriever.
Outside the scope of this post, but by "housed", I mean I have 2 csproj's sitting side by side.
MyApp.DataLayer.classic.csproj
and
MyApp.DataLayer.csproj
I find it easier to leave the default csproj to house the DotNetCore stuff. And I use the "classic.csproj" file to house the DotNet(classic). My assembly name and default namespace remain "MyApp.Datalayer"......the .classic is ONLY for the csrproj filename to distinquish.
I create two solution sln files too. MySolution.classic.sln and MySolution.sln.
It seems to be working.....with this ConnectionString abstraction I wrote above.
The ONLY conditional I have is on the (classic) AssemblyInfo.cs files.
#if(!NETCOREAPP2_1)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/* all the other stuff removed here */
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
APPEND:
Ok, here is the DotNet(Classic) version:
public class ConnectionStringWrapperDotNetClassicRetriever : IConnectionStringWrapperRetriever
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper returnItem = new ConnectionStringWrapper();
foreach(ConnectionStringSettings css in System.Configuration.ConfigurationManager.ConnectionStrings)
ConnectionStringEntry cse = new ConnectionStringEntry(css.Name, css.ConnectionString, css.ProviderName);
returnItem.ConnectionStringEntries.Add(cse);
if(returnItem.ConnectionStringEntries.Count == 1)
/* if there is only one, set the default name to that one */
returnItem.DefaultConnectionStringName = returnItem.ConnectionStringEntries.First().Name;
else
/*
<packages>
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
<package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
</packages>
*/
/* using Microsoft.Practices.EnterpriseLibrary.Data.Configuration; */
/* You can write you own way to handle a default database, or piggyback off of EnterpriseLibrary. You don't necessarily have to use EnterpriseLibrary.Data, you are simply piggybacking on their xml/configuration setup */
DatabaseSettings dbSettings = (DatabaseSettings)ConfigurationManager.GetSection("dataConfiguration");
returnItem.DefaultConnectionStringName = dbSettings.DefaultDatabase;
return returnItem;
And the app.config xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
<connectionStrings>
<clear/>
<add name="MyFirstConnectionStringName" connectionString="Server=.MyServerOne;Database=OneDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
<add name="MySecondConnectionStringName" connectionString="Server=.MyServerTwo;Database=TwoDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<dataConfiguration defaultDatabase="MyFirstConnectionStringName" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Key words:
DotNet DotNet .Net Core Classic Json Configuration ICollection scalar and collection support both dotnet and dotnetcore
add a comment |
First off, Nicholi's answer inspired me! Thanks Nicholi.
Second, I have a "List" solution rather than a IDictionary solution. It's not as smooth as the IDictionary solution.
This can also be dubbed "how to create a collection list for dot net core configuration"
Here we go:
first a shameless theft!
public class ConnectionStringEntry
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringEntry()
public ConnectionStringEntry(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringEntry(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
second, a "wrapper". I wanted to track a DefaultConnectionStringName...along side my List (collection) of Entries.
public class ConnectionStringWrapper
public string DefaultConnectionStringName get; set; = "";
public List<ConnectionStringEntry> ConnectionStringEntries get; set; = new List<ConnectionStringEntry>();
//public Dictionary<string, ConnectionStringEntry> ConnectionStringEntries get; set; = new Dictionary<string, ConnectionStringEntry>();
public ConnectionStringEntry GetDefaultConnectionStringEntry()
ConnectionStringEntry returnItem = this.GetConnectionStringEntry(this.DefaultConnectionStringName);
return returnItem;
public ConnectionStringEntry GetConnectionStringEntry(string name)
ConnectionStringEntry returnItem = null;
if (null != this.ConnectionStringEntries && this.ConnectionStringEntries.Any())
returnItem = this.ConnectionStringEntries.FirstOrDefault(ce => ce.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (null == returnItem)
throw new ArgumentOutOfRangeException(string.Format("No default ConnectionStringEntry found. (ConnectionStringEntries.Names='0', Search.Name='1')", this.ConnectionStringEntries == null ? string.Empty : string.Join(",", this.ConnectionStringEntries.Select(ce => ce.Name)), name));
return returnItem;
Now, my reading the json and mapping to a concrete settings object code:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConnectionStringWrapper settings = new ConnectionStringWrapper();
config.Bind("ConnectionStringWrapperSettings", settings);
Console.WriteLine("0, 1", settings.DefaultConnectionStringName, settings.ConnectionStringEntries.Count);
ConnectionStringEntry cse = settings.GetDefaultConnectionStringEntry();
My nuget packages:
.nugetpackagesmicrosoft.extensions.configuration2.1.1
.nugetpackagesmicrosoft.extensions.configuration.binder2.1.1
.nugetpackagesmicrosoft.extensions.configuration.json2.1.1
BONUS MATERIAL BELOW:
One of the things I am (trying) to so support a code base that can be deployed as DotNet 4.x ("classic" ?? as the term now??) and dotnet core.
To that end, I've written the above to provide an abstraction from the way DotNet(Classic) handles connection strings (xml, our old long time friend) and now the new cool kid on the block : DotNetCore with json.
To that end, I've written an interface:
public interface IConnectionStringWrapperRetriever
ConnectionStringWrapper RetrieveConnectionStringWrapper();
and I have an implementation for dotnetcore:
public class ConnectionStringWrapperDotNetCoreRetriever : IConnectionStringWrapperRetriever
public const string ConnectionStringWrapperSettingsJsonElementName = "ConnectionStringWrapperSettings";
private readonly IConfiguration config;
public ConnectionStringWrapperDotNetCoreRetriever(IConfiguration cnfg)
this.config = cnfg;
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper settings = new ConnectionStringWrapper();
this.config.Bind(ConnectionStringWrapperSettingsJsonElementName, settings);
return settings;
Oh yeah, the all important JSON setup:
"ConnectionStringWrapperSettings":
"DefaultConnectionStringName": "abc",
"ConnectionStringEntries": [
"Name": "abc",
"ConnectionString": "Server=myserver;Database=mydatabase;Trusted_Connection=True;MultipleActiveResultSets=true",
"ProviderName": "SomeProvider"
,
"Name": "def",
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "SomeProvider"
]
.............
For DotNet(classic), all you need to do is implement a second concrete for IConnectionStringWrapperRetriever, and do the magic.
Remember the below xml? (ha ha, its not that old yet!)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
(from https://docs.microsoft.com/en-us/dotnet/api/system.configuration.connectionstringsettingscollection?view=netframework-4.7.2)
Remember this stuff from EnterpriseLibrary?
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase="ConnStr1"/>
I'll leave the DotNet(Classic) implementation to the reader.
But now I inject IConnectionStringWrapperRetriever into my DataLayer classes.
I'm using Dapper, so I can fish a connection string using IConnectionStringWrapperRetriever.
If my project is "house" DotNet(Classic), I inject one version of IConnectionStringWrapperRetriever (not seen here, left to the reader). If my project is "housed" in DotNetCore I inject a second (shown above) version of IConnectionStringWrapperRetriever.
Outside the scope of this post, but by "housed", I mean I have 2 csproj's sitting side by side.
MyApp.DataLayer.classic.csproj
and
MyApp.DataLayer.csproj
I find it easier to leave the default csproj to house the DotNetCore stuff. And I use the "classic.csproj" file to house the DotNet(classic). My assembly name and default namespace remain "MyApp.Datalayer"......the .classic is ONLY for the csrproj filename to distinquish.
I create two solution sln files too. MySolution.classic.sln and MySolution.sln.
It seems to be working.....with this ConnectionString abstraction I wrote above.
The ONLY conditional I have is on the (classic) AssemblyInfo.cs files.
#if(!NETCOREAPP2_1)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/* all the other stuff removed here */
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
APPEND:
Ok, here is the DotNet(Classic) version:
public class ConnectionStringWrapperDotNetClassicRetriever : IConnectionStringWrapperRetriever
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper returnItem = new ConnectionStringWrapper();
foreach(ConnectionStringSettings css in System.Configuration.ConfigurationManager.ConnectionStrings)
ConnectionStringEntry cse = new ConnectionStringEntry(css.Name, css.ConnectionString, css.ProviderName);
returnItem.ConnectionStringEntries.Add(cse);
if(returnItem.ConnectionStringEntries.Count == 1)
/* if there is only one, set the default name to that one */
returnItem.DefaultConnectionStringName = returnItem.ConnectionStringEntries.First().Name;
else
/*
<packages>
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
<package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
</packages>
*/
/* using Microsoft.Practices.EnterpriseLibrary.Data.Configuration; */
/* You can write you own way to handle a default database, or piggyback off of EnterpriseLibrary. You don't necessarily have to use EnterpriseLibrary.Data, you are simply piggybacking on their xml/configuration setup */
DatabaseSettings dbSettings = (DatabaseSettings)ConfigurationManager.GetSection("dataConfiguration");
returnItem.DefaultConnectionStringName = dbSettings.DefaultDatabase;
return returnItem;
And the app.config xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
<connectionStrings>
<clear/>
<add name="MyFirstConnectionStringName" connectionString="Server=.MyServerOne;Database=OneDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
<add name="MySecondConnectionStringName" connectionString="Server=.MyServerTwo;Database=TwoDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<dataConfiguration defaultDatabase="MyFirstConnectionStringName" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Key words:
DotNet DotNet .Net Core Classic Json Configuration ICollection scalar and collection support both dotnet and dotnetcore
First off, Nicholi's answer inspired me! Thanks Nicholi.
Second, I have a "List" solution rather than a IDictionary solution. It's not as smooth as the IDictionary solution.
This can also be dubbed "how to create a collection list for dot net core configuration"
Here we go:
first a shameless theft!
public class ConnectionStringEntry
public String Name get; set;
public String ConnectionString get; set;
public String ProviderName get; set;
public ConnectionStringEntry()
public ConnectionStringEntry(String name, String connectionString)
: this(name, connectionString, null)
public ConnectionStringEntry(String name, String connectionString, String providerName)
this.Name = name;
this.ConnectionString = connectionString;
this.ProviderName = providerName;
second, a "wrapper". I wanted to track a DefaultConnectionStringName...along side my List (collection) of Entries.
public class ConnectionStringWrapper
public string DefaultConnectionStringName get; set; = "";
public List<ConnectionStringEntry> ConnectionStringEntries get; set; = new List<ConnectionStringEntry>();
//public Dictionary<string, ConnectionStringEntry> ConnectionStringEntries get; set; = new Dictionary<string, ConnectionStringEntry>();
public ConnectionStringEntry GetDefaultConnectionStringEntry()
ConnectionStringEntry returnItem = this.GetConnectionStringEntry(this.DefaultConnectionStringName);
return returnItem;
public ConnectionStringEntry GetConnectionStringEntry(string name)
ConnectionStringEntry returnItem = null;
if (null != this.ConnectionStringEntries && this.ConnectionStringEntries.Any())
returnItem = this.ConnectionStringEntries.FirstOrDefault(ce => ce.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
if (null == returnItem)
throw new ArgumentOutOfRangeException(string.Format("No default ConnectionStringEntry found. (ConnectionStringEntries.Names='0', Search.Name='1')", this.ConnectionStringEntries == null ? string.Empty : string.Join(",", this.ConnectionStringEntries.Select(ce => ce.Name)), name));
return returnItem;
Now, my reading the json and mapping to a concrete settings object code:
IConfiguration config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.Build();
ConnectionStringWrapper settings = new ConnectionStringWrapper();
config.Bind("ConnectionStringWrapperSettings", settings);
Console.WriteLine("0, 1", settings.DefaultConnectionStringName, settings.ConnectionStringEntries.Count);
ConnectionStringEntry cse = settings.GetDefaultConnectionStringEntry();
My nuget packages:
.nugetpackagesmicrosoft.extensions.configuration2.1.1
.nugetpackagesmicrosoft.extensions.configuration.binder2.1.1
.nugetpackagesmicrosoft.extensions.configuration.json2.1.1
BONUS MATERIAL BELOW:
One of the things I am (trying) to so support a code base that can be deployed as DotNet 4.x ("classic" ?? as the term now??) and dotnet core.
To that end, I've written the above to provide an abstraction from the way DotNet(Classic) handles connection strings (xml, our old long time friend) and now the new cool kid on the block : DotNetCore with json.
To that end, I've written an interface:
public interface IConnectionStringWrapperRetriever
ConnectionStringWrapper RetrieveConnectionStringWrapper();
and I have an implementation for dotnetcore:
public class ConnectionStringWrapperDotNetCoreRetriever : IConnectionStringWrapperRetriever
public const string ConnectionStringWrapperSettingsJsonElementName = "ConnectionStringWrapperSettings";
private readonly IConfiguration config;
public ConnectionStringWrapperDotNetCoreRetriever(IConfiguration cnfg)
this.config = cnfg;
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper settings = new ConnectionStringWrapper();
this.config.Bind(ConnectionStringWrapperSettingsJsonElementName, settings);
return settings;
Oh yeah, the all important JSON setup:
"ConnectionStringWrapperSettings":
"DefaultConnectionStringName": "abc",
"ConnectionStringEntries": [
"Name": "abc",
"ConnectionString": "Server=myserver;Database=mydatabase;Trusted_Connection=True;MultipleActiveResultSets=true",
"ProviderName": "SomeProvider"
,
"Name": "def",
"ConnectionString": "server=localhost;database=db2;username=user2;password=pass2;",
"ProviderName": "SomeProvider"
]
.............
For DotNet(classic), all you need to do is implement a second concrete for IConnectionStringWrapperRetriever, and do the magic.
Remember the below xml? (ha ha, its not that old yet!)
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<connectionStrings>
<add name="ConnStr1" connectionString="LocalSqlServer: data source=127.0.0.1;Integrated Security=SSPI;Initial Catalog=aspnetdb"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
(from https://docs.microsoft.com/en-us/dotnet/api/system.configuration.connectionstringsettingscollection?view=netframework-4.7.2)
Remember this stuff from EnterpriseLibrary?
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<dataConfiguration defaultDatabase="ConnStr1"/>
I'll leave the DotNet(Classic) implementation to the reader.
But now I inject IConnectionStringWrapperRetriever into my DataLayer classes.
I'm using Dapper, so I can fish a connection string using IConnectionStringWrapperRetriever.
If my project is "house" DotNet(Classic), I inject one version of IConnectionStringWrapperRetriever (not seen here, left to the reader). If my project is "housed" in DotNetCore I inject a second (shown above) version of IConnectionStringWrapperRetriever.
Outside the scope of this post, but by "housed", I mean I have 2 csproj's sitting side by side.
MyApp.DataLayer.classic.csproj
and
MyApp.DataLayer.csproj
I find it easier to leave the default csproj to house the DotNetCore stuff. And I use the "classic.csproj" file to house the DotNet(classic). My assembly name and default namespace remain "MyApp.Datalayer"......the .classic is ONLY for the csrproj filename to distinquish.
I create two solution sln files too. MySolution.classic.sln and MySolution.sln.
It seems to be working.....with this ConnectionString abstraction I wrote above.
The ONLY conditional I have is on the (classic) AssemblyInfo.cs files.
#if(!NETCOREAPP2_1)
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
/* all the other stuff removed here */
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
#endif
APPEND:
Ok, here is the DotNet(Classic) version:
public class ConnectionStringWrapperDotNetClassicRetriever : IConnectionStringWrapperRetriever
public ConnectionStringWrapper RetrieveConnectionStringWrapper()
ConnectionStringWrapper returnItem = new ConnectionStringWrapper();
foreach(ConnectionStringSettings css in System.Configuration.ConfigurationManager.ConnectionStrings)
ConnectionStringEntry cse = new ConnectionStringEntry(css.Name, css.ConnectionString, css.ProviderName);
returnItem.ConnectionStringEntries.Add(cse);
if(returnItem.ConnectionStringEntries.Count == 1)
/* if there is only one, set the default name to that one */
returnItem.DefaultConnectionStringName = returnItem.ConnectionStringEntries.First().Name;
else
/*
<packages>
<package id="EnterpriseLibrary.Common" version="6.0.1304.0" targetFramework="net45" />
<package id="EnterpriseLibrary.Data" version="6.0.1304.0" targetFramework="net45" />
</packages>
*/
/* using Microsoft.Practices.EnterpriseLibrary.Data.Configuration; */
/* You can write you own way to handle a default database, or piggyback off of EnterpriseLibrary. You don't necessarily have to use EnterpriseLibrary.Data, you are simply piggybacking on their xml/configuration setup */
DatabaseSettings dbSettings = (DatabaseSettings)ConfigurationManager.GetSection("dataConfiguration");
returnItem.DefaultConnectionStringName = dbSettings.DefaultDatabase;
return returnItem;
And the app.config xml:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
<connectionStrings>
<clear/>
<add name="MyFirstConnectionStringName" connectionString="Server=.MyServerOne;Database=OneDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
<add name="MySecondConnectionStringName" connectionString="Server=.MyServerTwo;Database=TwoDB;Trusted_Connection=True;MultipleActiveResultSets=true"
providerName="System.Data.SqlClient" />
</connectionStrings>
<dataConfiguration defaultDatabase="MyFirstConnectionStringName" />
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
Key words:
DotNet DotNet .Net Core Classic Json Configuration ICollection scalar and collection support both dotnet and dotnetcore
edited Nov 16 '18 at 13:45
answered Nov 15 '18 at 19:22
granadaCodergranadaCoder
15.2k55581
15.2k55581
add a comment |
add a comment |
Something like:
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
var conString = configurationRoot["ConnectionStrings:MyConnection"]);
add a comment |
Something like:
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
var conString = configurationRoot["ConnectionStrings:MyConnection"]);
add a comment |
Something like:
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
var conString = configurationRoot["ConnectionStrings:MyConnection"]);
Something like:
var configurationRoot = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
var conString = configurationRoot["ConnectionStrings:MyConnection"]);
answered Nov 28 '16 at 14:55
Derek BeattieDerek Beattie
8,35732543
8,35732543
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f40845542%2fhow-to-read-a-connectionstring-with-provider-in-net-core%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Your Connections.json is invalid. Your "conStrings" array have to much "}" . It should look like jsoneditoronline.org/?id=a00f0105a65d6a651d872ea9688d6147
– M. Wiśnicki
Nov 28 '16 at 13:57
5
Dude, you just posted connection string to your databases to public view. Consider to remove passwords at least!
– Maris
Nov 28 '16 at 14:09
@Maris: Doesn't matter, changed them before I posted - forgot one, but it was TrippleDES encrypted anyway. The datasource isn't confidential anyway.
– user6038265
Nov 28 '16 at 17:12