Saya memiliki string koneksi dan saya ingin dapat mengintip misalnya "Sumber Data". Apakah ada pengurai, atau apakah saya harus mencari string?
Saya memiliki string koneksi dan saya ingin dapat mengintip misalnya "Sumber Data". Apakah ada pengurai, atau apakah saya harus mencari string?
Jawaban:
Ya, ada System.Data.Common.DbConnectionStringBuilderkelasnya.
Kelas DbConnectionStringBuilder menyediakan kelas dasar dari mana pembangun string koneksi sangat diketik (SqlConnectionStringBuilder, OleDbConnectionStringBuilder, dan sebagainya) berasal. Pembuat string koneksi memungkinkan pengembang membuat string koneksi yang benar secara sintaksis, dan mem-parsing dan membangun kembali string koneksi yang ada.
Subclass yang menarik adalah:
System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
Misalnya, untuk "mengintip Sumber Data" dari string koneksi SQL-server, Anda dapat melakukan:
var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;
Ada penjual koneksi string spesifik pembangun dari berbagai penyedia seperti SqlConnectionStringBuilder, MySqlConnectionStringBuilder,SQLiteConnectionStringBuilder dll (sayangnya tidak ada antarmuka publik dari MS saat ini). Kalau tidak, Anda memiliki DbProviderFactory.CreateConnectionStringBuilder yang akan memberi Anda cara alternatif untuk menuliskannya dengan cara provider-agnostic. Anda perlu menentukan penyedia dalam file konfigurasi dan memiliki versi dll yang tepat tersedia. Untuk mis.,
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"];
Saya pernah menulis parsing manual untuk diri saya sendiri yang tidak memberi saya masalah. Akan sepele untuk memperluas ini untuk memberikan info tentang parameter lain (saat ini hanya untuk hal-hal sederhana seperti nama db, sumber data, nama pengguna dan kata sandi). Seperti ini atau lebih:
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;
}
Untuk ini, Anda tidak perlu sesuatu yang khusus dalam file konfigurasi, atau dll sama sekali. Containsdalam Whereklausa penting hanya jika Anda perlu mem-bypass koneksi yang diformat dengan buruk seperti di server = localhost;pp;mana tidak ppmenambah apa pun. Untuk berperilaku seperti pembangun normal (yang akan meledak dalam kasus ini) ubah Whereke
.Where(kvp => !string.IsNullOrWhitespace(kvp))
StringComparer.InvariantCultureIgnoreCase. Lihat ToDictionarykelebihan
';'atau '='password mereka. Saya telah menulis implementasi serupa dan belajar bahwa itu tidak bekerja dengan cara yang sulit. Astaga, koneksi string parsing sebenarnya jauh lebih sulit daripada yang saya kira!
Berikut adalah beberapa baris kode yang akan menguraikan string koneksi apa pun ke dalam kamus:
Dictionary<string, string> connStringParts = connString.Split(';')
.Select(t => t.Split(new char[] { '=' }, 2))
.ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);
Dan kemudian Anda dapat mengakses bagian mana saja:
string dataSource = connStringParts["Data Source"];
StringSplitOptions.RemoveEmptyEntrieske split pertama karena akan menyebabkan IndexOutOfRangepengecualian jika ada trailing;
SqlConnectiondengan SqlConnectionStringBuilder.
Gunakan SqlConnectionStringBuilder Sayangnya Anda harus menggunakan DB ConnectionStringBuilder khusus karena string koneksi berbeda.
Anda ingin menggunakan DbProviderFactory.CreateConnectionStringBuilder () yang memberikan Anda pembuat koneksi string / parser khusus untuk konektor Anda, tetapi tidak mengharuskan Anda untuk menggunakan kelas konektor tertentu.
Ya, Anda bisa melakukan ini menggunakan kelas ConnectionStringBuilder. Berikut adalah daftar implementasi DbConnectionStringBuilder yang tersedia untuk penyedia data standar:
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder
berikut adalah contoh contoh string koneksi parse dan menampilkan elemen-elemennya.
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);
Anda dapat menggunakan DbConnectionStringBuilder, dan Anda tidak memerlukan penyedia spesifik:
Kode berikut:
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"]);
Output ke konsol:
Data Source: data source value
Server: ServerValue
EDIT:
Karena DbConnectionStringBuilder mengimplementasikan IDictionary Anda dapat menyebutkan parameter string koneksi:
foreach (KeyValuePair<string, object> kv in builder)
{
Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}
Saya tidak terlalu menyukai semua jawaban di sini. Jadi inilah yang saya temukan.
Anda dapat menggunakan DbConnectionStringBuildersecara langsung:
var builder = new System.Data.Common.DbConnectionStringBuilder();
builder.ConnectionString = settings.ConnectionString;
var server = builder["server"];
Jadi saya menemukan semua jawaban yang ada kurang lebih salah. Saya berakhir dengan solusi sepele berikut:
class ConnectionStringParser: DbConnectionStringBuilder {
ConnectionStringParser(string c) { Connection = c; }
public override bool ShouldSerialize(string keyword) => true;
}
Parser ada di DbConnectionStringBuilder dan cukup mudah untuk didapatkan. Satu-satunya hal konyol yang harus kita lakukan adalah mengatur ShouldSerialize untuk selalu mengembalikan true untuk mencegah kehilangan komponen ketika mencoba untuk membulatkan string koneksi arbitrer.
DbConnectionStringBuildermemiliki fitur pemrosesan generik yang dapat digunakan tanpa menggunakan subclass:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }