Tengo una cadena de conexión y quiero poder ver, por ejemplo, "Fuente de datos". ¿Hay un analizador o tengo que buscar la cadena?
Tengo una cadena de conexión y quiero poder ver, por ejemplo, "Fuente de datos". ¿Hay un analizador o tengo que buscar la cadena?
Respuestas:
Sí, ahí está la System.Data.Common.DbConnectionStringBuilderclase.
La clase DbConnectionStringBuilder proporciona la clase base de la que derivan los constructores de cadenas de conexión fuertemente tipados (SqlConnectionStringBuilder, OleDbConnectionStringBuilder, etc.). Los creadores de cadenas de conexión permiten a los desarrolladores crear mediante programación cadenas de conexión sintácticamente correctas, y analizar y reconstruir cadenas de conexión existentes.
Las subclases de interés son:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Por ejemplo, para "ver el origen de datos" desde una cadena de conexión de servidor SQL, puede hacer lo siguiente:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Hay proveedores constructores de cadena de conexión específica de diversos proveedores, como SqlConnectionStringBuilder, MySqlConnectionStringBuilder, SQLiteConnectionStringBuilderetc (por desgracia no hay ninguna interfaz pública de la MS en esta ocasión). De lo contrario, tiene DbProviderFactory.CreateConnectionStringBuilder que le dará una forma alternativa de escribirlo de manera independiente del proveedor. Debería especificar el proveedor en el archivo de configuración y tener disponible la versión correcta de dll. Por ej.
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"];
Una vez había escrito un análisis manual para mí, lo que no me dio ningún problema. Sería trivial extender esto para dar información sobre otros parámetros (en este momento es solo para cosas simples como nombre de base de datos, fuente de datos, nombre de usuario y contraseña). Así o más o menos:
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 esto, no necesita nada especial en el archivo de configuración, ni ningún dll. Containsen la Wherecláusula es importante solo si necesita omitir cadenas de conexiones mal formateadas como server = localhost;pp;donde no se ppagrega nada. Para comportarse como constructores normales (que explotarían en estos casos) cambie el Wherea
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. Ver la ToDictionarysobrecarga
';'o una '='contraseña. Había escrito una implementación similar y aprendí que no funciona de la manera difícil. Gosh, el análisis de la cadena de conexión es en realidad mucho más difícil de lo que pensaba.
Aquí hay un par de líneas de código que analizarían cualquier cadena de conexión en un diccionario:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
Y luego puedes acceder a cualquier parte:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntriesen la primera división, ya que causará una IndexOutOfRangeexcepción si hay un final;
SqlConnectioncon el SqlConnectionStringBuilder.
Use el SqlConnectionStringBuilder Lamentablemente, tendrá que usar un ConnectionStringBuilder específico de la base de datos, ya que las cadenas de conexión difieren.
Desea usar DbProviderFactory.CreateConnectionStringBuilder () que le proporciona un generador / analizador de cadenas de conexión específico para su conector, pero no requiere que use ninguna clase específica de conector.
Sí, puede hacerlo utilizando las clases ConnectionStringBuilder. Aquí está la lista de implementaciones de DbConnectionStringBuilder disponibles para proveedores de datos estándar:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Aquí hay un ejemplo de una cadena de conexión de análisis y muestra sus 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);
Puede usar DbConnectionStringBuilder y no necesita ningún proveedor específico:
El siguiente código:
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"]);
Salidas a la consola:
Data Source: data source value
Server: ServerValue
EDITAR:
Como DbConnectionStringBuilder implementa IDictionary, puede enumerar los parámetros de la cadena de conexión:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Realmente no me gustaron todas las respuestas aquí. Así que aquí está lo que encontré.
Puedes usar DbConnectionStringBuilderdirectamente:
var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];
Entonces descubrí que todas las respuestas existentes estaban más o menos equivocadas. Terminé con la siguiente solución trivial:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
El analizador está en DbConnectionStringBuilder y es bastante fácil de encontrar. La única cosa tonta que tenemos que hacer es configurar a DoesSerialize para que siempre devuelva verdadero para evitar la pérdida de componentes cuando se intentan las cadenas de conexión arbitrarias de ida y vuelta.
DbConnectionStringBuildertiene características de procesamiento genéricas que se pueden usar sin usar subclases:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }