Ich habe eine Verbindungszeichenfolge und möchte beispielsweise "Datenquelle" sehen können. Gibt es einen Parser oder muss ich die Zeichenfolge durchsuchen?
Ich habe eine Verbindungszeichenfolge und möchte beispielsweise "Datenquelle" sehen können. Gibt es einen Parser oder muss ich die Zeichenfolge durchsuchen?
Antworten:
Ja, da ist die System.Data.Common.DbConnectionStringBuilderKlasse.
Die DbConnectionStringBuilder-Klasse stellt die Basisklasse bereit, von der die stark typisierten Builder für Verbindungszeichenfolgen (SqlConnectionStringBuilder, OleDbConnectionStringBuilder usw.) abgeleitet sind. Mit den Buildern für Verbindungszeichenfolgen können Entwickler programmgesteuert syntaktisch korrekte Verbindungszeichenfolgen erstellen und vorhandene Verbindungszeichenfolgen analysieren und neu erstellen.
Die interessierenden Unterklassen sind:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Um beispielsweise die Datenquelle aus einer SQL-Server-Verbindungszeichenfolge herauszuschauen, haben Sie folgende Möglichkeiten:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Es gibt herstellerspezifische Verbindungszeichenfolge Bauer von verschiedenen Anbietern wie SqlConnectionStringBuilder, MySqlConnectionStringBuilder, SQLiteConnectionStringBuilderusw. (leider gibt es keine öffentliche Schnittstelle von MS dieses Mal). Andernfalls haben Sie DbProviderFactory.CreateConnectionStringBuilder , mit dem Sie es auf alternative Weise anbieterunabhängig schreiben können. Sie müssten den Anbieter in der Konfigurationsdatei angeben und die richtige Version der DLL zur Verfügung haben. Zum Beispiel
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"];
Ich hatte einmal eine manuelle Analyse für mich geschrieben, die mir keine Probleme bereitete. Es wäre trivial, dies zu erweitern, um Informationen zu anderen Parametern zu erhalten (derzeit nur für einfache Dinge wie Datenbankname, Datenquelle, Benutzername und Passwort). So oder 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;
}
Dafür benötigen Sie nichts Besonderes in der Konfigurationsdatei oder überhaupt eine DLL. ContainsDie WhereKlausel in ist nur dann wichtig, wenn Sie schlecht formatierte Verbindungszeichenfolgen umgehen müssen, z. B. server = localhost;pp;where ppfügt nichts hinzu. Um sich wie normale Builder zu verhalten (die in diesen Fällen explodieren würden), ändern Sie das Wherein
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. Siehe die ToDictionaryÜberladung
';'oder ein '='Kennwort in seinem Kennwort hat. Ich hatte eine ähnliche Implementierung geschrieben und festgestellt, dass es nicht auf die harte Tour funktioniert. Meine Güte, das Parsen von Verbindungszeichenfolgen ist tatsächlich viel schwieriger als ich dachte!
Hier sind ein paar Codezeilen, die jede Verbindungszeichenfolge in ein Wörterbuch analysieren:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
Und dann können Sie auf jedes Teil zugreifen:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntriesin die erste Teilung, da dies eine IndexOutOfRangeAusnahme verursacht, wenn es ein Trailing gibt;
SqlConnectionmit der erstellen kann SqlConnectionStringBuilder.
Verwenden des SqlConnectionStringBuilder Leider müssen Sie einen DB-spezifischen ConnectionStringBuilder verwenden, da sich die Verbindungszeichenfolgen unterscheiden.
Sie möchten DbProviderFactory.CreateConnectionStringBuilder () verwenden , das Ihnen einen für Ihren Connector spezifischen Builder / Parser für Verbindungszeichenfolgen bereitstellt, für den Sie jedoch keine Connector-spezifischen Klassen verwenden müssen.
Ja, Sie können dies mit ConnectionStringBuilder-Klassen tun. Hier ist die Liste der verfügbaren DbConnectionStringBuilder-Implementierungen für Standarddatenanbieter:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Hier finden Sie ein Beispiel für eine Analyse-Verbindungszeichenfolge und deren Elemente.
string conString = @"Data Source=.\sqlexpress;" +
"Database=Northwind;Integrated Security=SSPI;" +
"Min Pool Size=5;Max Pool Size=15;Connection Reset=True;" +
"Connection Lifetime=600;";
// Parse the SQL Server connection string and display it's properties
SqlConnectionStringBuilder objSB1 = new SqlConnectionStringBuilder(conString);
Response.Write("<b>Parsed SQL Connection String Parameters:</b>");
Response.Write(" <br/> Database Source = " + objSB1.DataSource);
Response.Write(" <br/> Database = " + objSB1.InitialCatalog);
Response.Write(" <br/> Use Integrated Security = " + objSB1.IntegratedSecurity);
Response.Write(" <br/> Min Pool Size = " + objSB1.MinPoolSize);
Response.Write(" <br/> Max Pool Size = " + objSB1.MaxPoolSize);
Response.Write(" <br/> Lifetime = " + objSB1.LoadBalanceTimeout);
Sie können DbConnectionStringBuilder verwenden und benötigen keinen bestimmten Anbieter:
Der folgende Code:
var cnstr = "Data Source=data source value;Server=ServerValue";
var builder = new DbConnectionStringBuilder();
builder.ConnectionString = cnstr;
Console.WriteLine("Data Source: {0}", builder["Data Source"]);
Console.WriteLine("Server: {0}", builder["Server"]);
Ausgaben an die Konsole:
Data Source: data source value
Server: ServerValue
BEARBEITEN:
Da DbConnectionStringBuilder IDictionary implementiert, können Sie die Verbindungszeichenfolgenparameter auflisten:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Alle Antworten hier haben mir nicht wirklich gefallen. Also hier ist was ich gefunden habe.
Sie können DbConnectionStringBuilderdirekt verwenden:
var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];
Also fand ich, dass alle vorhandenen Antworten mehr oder weniger falsch waren. Am Ende hatte ich die folgende triviale Lösung:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
Der Parser befindet sich in DbConnectionStringBuilder und ist ziemlich einfach zu erreichen. Das einzig Dumme, was wir tun müssen, ist, ShouldSerialize so einzustellen, dass immer true zurückgegeben wird, um zu verhindern, dass Komponenten verloren gehen, wenn versucht wird, beliebige Verbindungszeichenfolgen zu umgehen.
DbConnectionStringBuilderverfügt über generische Verarbeitungsfunktionen, die ohne Verwendung von Unterklassen verwendet werden können:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }