217 votes

Existe-t-il un analyseur syntaxique de chaîne de connexion en C# ?

J'ai une chaîne de connexion et je veux être capable d'extraire par exemple "Data Source". Existe-t-il un analyseur syntaxique ou dois-je rechercher la chaîne de caractères ?

355voto

Ani Points 59747

Oui, il y a le System.Data.Common.DbConnectionStringBuilder classe.

La classe DbConnectionStringBuilder fournit la classe de base à partir de laquelle la chaîne de connexion fortement typée construites (SqlConnectionStringBuilder, OleDbConnectionStringBuilder, etc. ). Les constructeurs de chaînes de connexion permettent aux développeurs de de créer par programme des chaînes de connexion syntaxiquement correctes, d'analyser et de et reconstruire des chaînes de connexion de connexion existantes.

Les sous-classes d'intérêt sont :

System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder

Par exemple, pour "consulter la source de données" à partir d'une chaîne de connexion au serveur SQL, vous pouvez procéder comme suit :

var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;

12 votes

La classe de base DbConnectionStringBuilder possède des fonctionnalités de traitement génériques qui peuvent être utilisées sans avoir recours à des sous-classes : if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }

47voto

nawfal Points 13500

Il existe des constructeurs de chaînes de connexion spécifiques à chaque fournisseur, tels que SqlConnectionStringBuilder , MySqlConnectionStringBuilder , SQLiteConnectionStringBuilder etc (malheureusement, il n'y a pas d'interface publique de MS pour le moment). Sinon, vous avez DbProviderFactory.CreateConnectionStringBuilder qui vous donnera une autre façon de l'écrire, sans tenir compte du fournisseur. Vous devrez spécifier le fournisseur dans le fichier de configuration et avoir la bonne version de la dll disponible. Par exemple..,

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"];

J'ai déjà écrit une analyse manuelle pour moi-même qui ne m'a posé aucun problème. Il serait trivial d'étendre cela pour donner des informations sur d'autres paramètres (pour l'instant, cela ne concerne que des choses simples comme le nom de la base de données, la source de données, le nom d'utilisateur et le mot de passe). Comme ceci ou ainsi :

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;
}

Pour cela, vous n'avez besoin de rien de spécial dans le fichier de configuration, ni d'aucune dll. Contains sur Where n'est importante que si vous devez contourner des chaînes de connexion mal formatées telles que server = localhost;pp; donde pp n'ajoute rien. Pour se comporter comme des constructeurs normaux (qui exploseraient dans ces cas-là), changez le paramètre Where a

.Where(kvp => !string.IsNullOrWhitespace(kvp))

0 votes

@Icarus pas vraiment puisque le comparateur de clés du dictionnaire est StringComparer.InvariantCultureIgnoreCase . Voir le ToDictionary surcharge

1 votes

Oui, vous avez raison, j'ai juste écrit un test rapide. Je vais supprimer mon commentaire original puisqu'il est erroné.

4 votes

Votre méthode GetValue() ne fonctionnera pas dans les cas où, par exemple, l'utilisateur a une ';' ou un '=' dans leur mot de passe. J'avais écrit une implémentation similaire et j'ai appris à la dure que cela ne fonctionnait pas. Bon sang, l'analyse des chaînes de connexion est en fait beaucoup plus difficile que je ne le pensais !

25voto

codeprose-sam Points 94

Voici quelques lignes de code qui analyseront n'importe quelle chaîne de connexion dans un dictionnaire :

Dictionary<string, string> connStringParts = connString.Split(';')
    .Select(t => t.Split(new char[] { '=' }, 2))
    .ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);

Et ensuite vous pouvez accéder à n'importe quelle partie :

string dataSource = connStringParts["Data Source"];

3 votes

Intelligent, la seule chose que je changerais serait d'inclure StringSplitOptions.RemoveEmptyEntries au premier fractionnement, car cela provoquera un IndexOutOfRange exception s'il y a un ;

2 votes

Cela fonctionne, mais les constructeurs de chaînes de connexion sont plus robustes. Un code tel que celui-ci lancera des exceptions de bas niveau au lieu d'erreurs d'analyse plus significatives dans le cas de chaînes de connexion invalides.

0 votes

Cela m'a aidé à analyser une chaîne de connexion ADO pour pouvoir construire un équivalent. SqlConnection avec le SqlConnectionStringBuilder .

7voto

David Thielen Points 3176

Vous voulez utiliser DbProviderFactory.CreateConnectionStringBuilder () qui vous fournit un constructeur/parseur de chaîne de connexion spécifique à votre connecteur, mais ne vous oblige pas à utiliser des classes spécifiques au connecteur.

6voto

Erno de Weerd Points 30391

Utilisez le SqlConnectionStringBuilder Malheureusement, vous devrez utiliser un ConnectionStringBuilder spécifique à la DB, car les chaînes de connexion sont différentes.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X