Eu tenho uma cadeia de conexão e desejo poder visualizar, por exemplo, "Fonte de dados". Existe um analisador ou tenho que pesquisar a string?
Eu tenho uma cadeia de conexão e desejo poder visualizar, por exemplo, "Fonte de dados". Existe um analisador ou tenho que pesquisar a string?
Respostas:
Sim, tem a System.Data.Common.DbConnectionStringBuilderaula.
A classe DbConnectionStringBuilder fornece a classe base da qual derivam os construtores de cadeias de conexão fortemente tipadas (SqlConnectionStringBuilder, OleDbConnectionStringBuilder e assim por diante). Os construtores de cadeias de conexão permitem que os desenvolvedores criem programaticamente cadeias de conexão sintaticamente corretas e analisem e reconstruam as cadeias de conexão existentes.
As subclasses de interesse são:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Por exemplo, para "descobrir a fonte de dados" de uma cadeia de conexão do servidor SQL, você pode:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Há fornecedores construtores de cadeia de ligação específica de vários fornecedores como SqlConnectionStringBuilder, MySqlConnectionStringBuilder, SQLiteConnectionStringBuilderetc (infelizmente não há nenhuma interface pública de MS neste momento). Caso contrário, você tem o DbProviderFactory.CreateConnectionStringBuilder, que fornecerá uma maneira alternativa de escrevê-lo de maneira independente de provedor. Você precisaria especificar o provedor no arquivo de configuração e ter a versão correta da DLL disponível. Por exemplo,
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"];
Uma vez eu escrevi uma análise manual para mim, o que não me causou nenhum problema. Seria trivial estender isso para fornecer informações sobre outros parâmetros (agora é apenas para coisas simples, como nome db, fonte de dados, nome de usuário e senha). Assim ou assim:
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;
}
Para isso, você não precisa de nada de especial no arquivo de configuração ou de qualquer dll. Containsna Wherecláusula é importante apenas se você precisar ignorar as cadeias de conexão mal formatadas, como server = localhost;pp;where ppadiciona a nada. Para se comportar como construtores normais (que explodiriam nesses casos), mude Wherepara
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. Veja a ToDictionarysobrecarga
';'ou uma '='senha. Eu escrevi uma implementação semelhante e aprendi que não funciona da maneira mais difícil. Puxa, a análise de cadeia de conexão é realmente muito mais difícil do que eu pensava!
Aqui estão algumas linhas de código que analisariam qualquer cadeia de conexão em um dicionário:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
E então você pode acessar qualquer parte:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntriesa primeira divisão, uma vez que irá causar uma IndexOutOfRangeexceção se houver uma fuga;
SqlConnectioncom o SqlConnectionStringBuilder.
Use o SqlConnectionStringBuilder Infelizmente, você precisará usar um ConnectionStringBuilder específico do banco de dados, pois as seqüências de conexão diferem.
Você deseja usar DbProviderFactory.CreateConnectionStringBuilder () que fornece um construtor / analisador de cadeias de conexão específico para o seu conector, mas não requer o uso de nenhuma classe específica do conector.
Sim, você pode fazer isso usando as classes ConnectionStringBuilder. Aqui está a lista de implementações disponíveis do DbConnectionStringBuilder para provedores de dados padrão:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Aqui está um exemplo de cadeia de conexão de análise e exibe seus elementos.
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);
Você pode usar o DbConnectionStringBuilder e não precisa de nenhum provedor específico:
O código a seguir:
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"]);
Saídas para o console:
Data Source: data source value
Server: ServerValue
EDITAR:
Como o DbConnectionStringBuilder implementa o IDictionary, você pode enumerar os parâmetros da cadeia de conexão:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Eu realmente não gostei de todas as respostas aqui. Então aqui está o que eu encontrei.
Você pode usar DbConnectionStringBuilderdiretamente:
var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];
Então, descobri que todas as respostas existentes estavam mais ou menos erradas. Acabei com a seguinte solução trivial:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
O analisador está no DbConnectionStringBuilder e é muito fácil de acessar. A única coisa boba que precisamos fazer é definir ShouldSerialize para sempre retornar true, a fim de evitar a perda de componentes ao tentar arredondar seqüências de conexão arbitrárias.
DbConnectionStringBuildertem características de processamento genéricas que podem ser usados sem usar subclasses:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }