Bir bağlantı dizesi var ve örneğin "Veri Kaynağı" gözetlemek istiyorum. Bir ayrıştırıcı var mı, yoksa dizeyi aramak zorunda mıyım?
Bir bağlantı dizesi var ve örneğin "Veri Kaynağı" gözetlemek istiyorum. Bir ayrıştırıcı var mı, yoksa dizeyi aramak zorunda mıyım?
Yanıtlar:
Evet, System.Data.Common.DbConnectionStringBuildersınıf var.
DbConnectionStringBuilder sınıfı, güçlü yazılan bağlantı dizesi oluşturucularının (SqlConnectionStringBuilder, OleDbConnectionStringBuilder vb.) Türetildiği temel sınıfı sağlar. Bağlantı dizesi oluşturucuları, geliştiricilerin programlı olarak sözdizimsel olarak doğru bağlantı dizeleri oluşturmasına ve varolan bağlantı dizelerini ayrıştırıp yeniden oluşturmasına olanak tanır.
İlgilenilen alt sınıflar:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Örneğin, bir SQL sunucusu bağlantı dizesinden "Veri Kaynağını gözetlemek" için şunları yapabilirsiniz:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Gibi çeşitli sağlayıcılardan satıcıya özel bağlantı dizesi inşaatçılar vardır SqlConnectionStringBuilder, MySqlConnectionStringBuilder, SQLiteConnectionStringBuildervb (maalesef MS bu kez hiçbir kamu arayüz yoktur). Aksi takdirde , sağlayıcıya agnostik bir yol yazmak için alternatif bir yol sağlayacak DbProviderFactory.CreateConnectionStringBuilder var . Yapılandırma dosyasında sağlayıcı belirtmeniz ve doğru dll sürümüne sahip olmanız gerekir. Örneğin,
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"];
Bir keresinde kendime manuel ayrıştırma yazdım, bu da bana hiç sorun vermedi. Diğer parametreler hakkında bilgi vermek için bunu genişletmek önemsiz olacaktır (şu anda sadece db adı, veri kaynağı, kullanıcı adı ve şifre gibi basit şeyler için). Bunun gibi:
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;
}
Bunun için yapılandırma dosyasında özel bir şeye veya herhangi bir dll'ye ihtiyacınız yoktur. Containsiçinde Wheremaddesi Eğer bypass etmeyi gibi, kötü biçimlendirilmiş ConnectionStrings yalnızca ihtiyacı önemlidir server = localhost;pp;nerede pphiçbir şey ekler. Değiştirin (bu durumlarda patlayabilir olan) Normal inşaatçılar gibi davranmaya WhereTo
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. ToDictionaryAşırı yüklemeye bakın
';'veya bir olduğu durumlarda çalışmaz '='. Benzer bir uygulama yazmıştım ve bunun zor yoldan çalışmadığını öğrendim. Tanrım, bağlantı dizesi ayrıştırma aslında düşündüğümden çok daha zor!
Herhangi bir bağlantı dizesini sözlüğe ayrıştıracak birkaç kod satırı:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
Ve sonra herhangi bir bölüme erişebilirsiniz:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntriesilk bölüme dahil olacaktı, çünkü IndexOutOfRangebir iz varsa istisnaya neden olacak;
SqlConnectionolan SqlConnectionStringBuilder.
SqlConnectionStringBuilder kullanın Maalesef bağlantı dizeleri farklı olduğundan DB'ye özel ConnectionStringBuilder kullanmanız gerekir.
Bağlayıcınıza özgü bir bağlantı dizesi oluşturucu / ayrıştırıcı sağlayan, ancak bağlayıcıya özgü sınıflar kullanmanızı gerektirmeyen DbProviderFactory.CreateConnectionStringBuilder () yöntemini kullanmak istiyorsunuz .
Evet, bunu ConnectionStringBuilder Sınıflarını kullanarak yapabilirsiniz. Standart veri sağlayıcıları için mevcut DbConnectionStringBuilder uygulamalarının listesi:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
ayrıştırma bağlantı dizesinin örnek örneği ve öğelerini görüntüler.
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 kullanabilirsiniz ve herhangi bir belirli sağlayıcıya ihtiyacınız yoktur:
Aşağıdaki kod:
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"]);
Konsol çıkışları:
Data Source: data source value
Server: ServerValue
DÜZENLE:
DbConnectionStringBuilder IDictionary uyguladığından, bağlantı dizesi parametrelerini numaralandırabilirsiniz:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Bu yüzden mevcut tüm cevapların aşağı yukarı yanlış olduğunu gördüm. Sonunda şu önemsiz çözümü buldum:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
Ayrıştırıcı DbConnectionStringBuilder ve almak çok kolaydır. Yapmamız gereken tek saçma şey, keyfi bağlantı dizelerini döndürmeye çalışırken bileşenlerin kaybedilmesini önlemek için ShouldSerialize'ı her zaman true değerine döndürecek şekilde ayarlamaktır.
DbConnectionStringBuilder, alt sınıflar kullanılmadan kullanılabilecek genel işleme özelliklerine sahiptir:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }