I have a connection string and I want to be able to peek out for example \"Data Source\". Is there a parser, or do I have to search the string?
So I found all of the existing answers were more or less wrong. I ended up with the following trivial solution:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
The parser is in DbConnectionStringBuilder and pretty much easy to get at. The only silly thing we have to do is set ShouldSerialize to always return true to prevent losing components when trying to round trip arbitrary connection strings.
There are vendor specific connection string builders from various providers like SqlConnectionStringBuilder
, MySqlConnectionStringBuilder
, SQLiteConnectionStringBuilder
etc (unfortunately there is no public interface from MS this time). Otherwise you have DbProviderFactory.CreateConnectionStringBuilder which will give you an alternate way to write it provider-agnostic way. You would need to specify provider in config file and have the right version of dll available. For eg.,
var c = "server=localhost;User Id=root;database=ppp";
var f = DbProviderFactories.GetFactory("MySql.Data.MySqlClient"); //your provider
var b = f.CreateConnectionStringBuilder();
b.ConnectionString = c;
var s = b["data source"];
var d = b["database"];
I had once written manual parsing for myself which did not give me any trouble. It would be trivial to extend this to give info on other parameters (right now its only for simple things like db name, data source, username and password). Like this or so:
static readonly string[] serverAliases = { "server", "host", "data source", "datasource", "address",
"addr", "network address" };
static readonly string[] databaseAliases = { "database", "initial catalog" };
static readonly string[] usernameAliases = { "user id", "uid", "username", "user name", "user" };
static readonly string[] passwordAliases = { "password", "pwd" };
public static string GetPassword(string connectionString)
{
return GetValue(connectionString, passwordAliases);
}
public static string GetUsername(string connectionString)
{
return GetValue(connectionString, usernameAliases);
}
public static string GetDatabaseName(string connectionString)
{
return GetValue(connectionString, databaseAliases);
}
public static string GetServerName(string connectionString)
{
return GetValue(connectionString, serverAliases);
}
static string GetValue(string connectionString, params string[] keyAliases)
{
var keyValuePairs = connectionString.Split(';')
.Where(kvp => kvp.Contains('='))
.Select(kvp => kvp.Split(new char[] { '=' }, 2))
.ToDictionary(kvp => kvp[0].Trim(),
kvp => kvp[1].Trim(),
StringComparer.InvariantCultureIgnoreCase);
foreach (var alias in keyAliases)
{
string value;
if (keyValuePairs.TryGetValue(alias, out value))
return value;
}
return string.Empty;
}
For this you don't need anything special in config file, or any dll at all. Contains
in Where
clause is important only if you need to bypass poorly formatted connectionstrings like server = localhost;pp;
where pp
adds to nothing. To behave like normal builders (which would explode in these cases) change the Where
to
.Where(kvp => !string.IsNullOrWhitespace(kvp))
Use the SqlConnectionStringBuilder Unfortunately you will have to use a DB specific ConnectionStringBuilder as the connection strings differ.