У мене є рядок підключення, і я хочу мати можливість зазирнути, наприклад, "Джерело даних". Чи є аналізатор чи мені потрібно шукати рядок?
У мене є рядок підключення, і я хочу мати можливість зазирнути, наприклад, "Джерело даних". Чи є аналізатор чи мені потрібно шукати рядок?
Відповіді:
Так, є System.Data.Common.DbConnectionStringBuilderклас.
Клас DbConnectionStringBuilder забезпечує базовий клас, з якого виводяться сильно набрані будівельники струнних з'єднань (SqlConnectionStringBuilder, OleDbConnectionStringBuilder тощо). Конструктори рядків підключення дозволяють розробникам програмно створювати синтаксично правильні рядки з'єднання та аналізувати та відновлювати існуючі рядки з'єднання.
Цікавими підкласами є:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Наприклад, щоб "виглянути джерело даних" з рядка з'єднання SQL-сервера, ви можете зробити:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Є постачальник струнні певної зв'язку будівельники з різних провайдерів , як SqlConnectionStringBuilder, MySqlConnectionStringBuilder, і SQLiteConnectionStringBuilderт.д. ( до жаль , не існує загальнодоступного інтерфейсу від MS на цей раз). В іншому випадку у вас є DbProviderFactory.CreateConnectionStringBuilder, який дасть вам альтернативний спосіб написати це провайдер-агностический спосіб. Вам потрібно буде вказати провайдера у конфігураційному файлі та мати правильну версію dll. Наприклад,
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"];
Я колись писав ручний розбір для себе, який не доставляв мені ніяких проблем. Це було б тривіально розширити це, щоб надати інформацію про інші параметри (зараз це лише для простих речей, таких як ім'я db, джерело даних, ім'я користувача та пароль). Ось так чи так:
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;
}
Для цього вам не потрібно нічого особливого в конфігураційному файлі або взагалі будь-який dll. Containsв Whereпункті важливо лише в тому випадку, якщо вам потрібно обійти погано відформатовані рядки з'єднання, наприклад, server = localhost;pp;де ppнічого не додається. Щоб поводитись як звичайні будівельники (які вибухнуть у цих випадках), змініть Whereна
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. Дивіться ToDictionaryперевантаження
';'або '='в їх пароль. Я написав подібну реалізацію і дізнався, що це не дуже важко. Боже, розбір рядків підключення насправді набагато складніше, ніж я думав!
Ось пара рядків коду, який би розібрав будь-який рядок з'єднання у словнику:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
І тоді ви можете отримати доступ до будь-якої частини:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntriesдо першого розколу, оскільки це спричинить IndexOutOfRangeвиняток, якщо буде кінець;
SqlConnectionз SqlConnectionStringBuilder.
Використовуйте SqlConnectionStringBuilder На жаль, вам доведеться використовувати специфічні для DB ConnectionStringBuilder, оскільки рядки з'єднання відрізняються.
Ви хочете використовувати DbProviderFactory.CreateConnectionStringBuilder (), який надає вам конструктор / аналізатор рядків з'єднання, характерний для вашого роз'єму, але не вимагає від вас використання будь-яких класів для конкретних з'єднань.
Так, це можна зробити за допомогою класів ConnectionStringBuilder. Ось перелік доступних реалізацій DbConnectionStringBuilder для стандартних постачальників даних:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
ось приклад прикладу рядка з'єднання для розбору та відображення його елементів.
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);
Ви можете використовувати DbConnectionStringBuilder, і вам не потрібен конкретний постачальник:
Наступний код:
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"]);
Виходи на консоль:
Data Source: data source value
Server: ServerValue
Редагувати:
Оскільки DbConnectionStringBuilder реалізує IDictionary, ви можете перерахувати параметри рядка з'єднання:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Мені не дуже сподобалися всі відповіді тут. Отже ось що я знайшов.
Ви можете використовувати DbConnectionStringBuilderбезпосередньо:
var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];
Тож я виявив, що всі існуючі відповіді були більш-менш помилковими. Я закінчив таке банальне рішення:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
Парсер знаходиться в DbConnectionStringBuilder і в ньому дуже легко потрапити. Єдине нерозумне, що нам потрібно зробити, це встановити ShouldSerialize, щоб завжди повертати true, щоб запобігти втраті компонентів при спробі заокруглення довільних рядків зв'язку.
DbConnectionStringBuilderмає загальні функції обробки, які можна використовувати без використання підкласів:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }