C # herhangi bir bağlantı dizesi ayrıştırıcı var mı?


181

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:


305

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;

6
Temel sınıf 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; }
Olivier Jacot-Descombes

41

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))

@Icarus aslında sözlüğün anahtar karşılaştırıcı olduğu için değil StringComparer.InvariantCultureIgnoreCase. ToDictionaryAşırı yüklemeye bakın
nawfal

1
Evet, haklısın, kısa bir test yazdım. Yanlış olduğu için orijinal yorumumu silecek.
Icarus

3
GetValue () yönteminiz, örneğin kullanıcının parolasında bir ';'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!
Philip Atz

@Joshua Umarım manuel ayrıştırma bölümünden bahsediyorsunuzdur. Lütfen cevapları kusursuz ve savaşla test edilmiş çözümlerden ziyade üzerinde çalışılabilecek bir başlangıç ​​noktası olarak alın. Umarım bilgi bırakmayan yorumlardan daha değerlidirler. Ayrıca oy kullanmakta serbestsiniz. Bildiğim kadarıyla, daha fazla yapılması gereken şey ayrıştırma standartlarına uymaktır. MS'in msdn'de bir tane var ve değişiklik yapmak aklımda uzun sürdü. Keşke hepimiz zaman olsaydı. '@' hepsi lütfen Philip Atz'ın yorumunda önemli olanları göz önünde bulundurun.
nawfal

@nawfal: Buraya geldim ve çözdüğümde bir cevap bıraktım.
Joshua

15

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

3
Akıllı, değiştireceğim tek şey StringSplitOptions.RemoveEmptyEntriesilk bölüme dahil olacaktı, çünkü IndexOutOfRangebir iz varsa istisnaya neden olacak;
Scott Chamberlain

2
Bu çalışır, ancak bağlantı dizesi oluşturucuları daha sağlamdır. Bunun gibi kodlar, geçersiz bağlantı dizeleri durumunda daha anlamlı ayrıştırma hataları yerine düşük düzey özel durumlar atar.
Sam

Bu Bir eşdeğer inşa edebileceğini yüzden beni bir ADO bağlantı dizesi ayrıştırmak yardımcı SqlConnectionolan SqlConnectionStringBuilder.
Holistic Developer

Burada bazı uyarılar var. Örneğin, bağlantı dizesi değerleri tırnak içine alınabilir.
Seva Alekseyev



4

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

4

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, bağlantı dizesinin yukarıdaki stackoverflow.com/a/15529085/534109 bölümünde belirtildiği gibi her zaman doğru olmayan bir "Veri Kaynağı" değerine vb. Sahip olduğunu zaten bildiğinizi varsayar .
Tieson T.

Cevabım özellikle op'un ne istediğini ekliyor: 'Örneğin "Veri Kaynağı" na göz atmak istiyorum
Jesús López

Tüm bağlantı dizesi parametrelerini göstermek için düzenledim.
Jesús López

1

Buradaki tüm cevapları gerçekten sevmedim. İşte bulduğum şey.

.NET Core ile

DbConnectionStringBuilderDoğrudan kullanabilirsiniz :

var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];

0

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.


2
Mevcut cevapların nesi yanlıştı? Ya da çözümünüz neyi düzeltiyor? Açıklama yardımcı olacaktır.
nawfal
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.