Có trình phân tích chuỗi kết nối nào trong C # không?


181

Tôi có một chuỗi kết nối và tôi muốn có thể xem ra ví dụ "Nguồn dữ liệu". Có một trình phân tích cú pháp, hoặc tôi phải tìm kiếm chuỗi?

Câu trả lời:


305

Vâng, có System.Data.Common.DbConnectionStringBuilderlớp học.

Lớp DbConnectionStringBuilder cung cấp lớp cơ sở mà từ đó các trình xây dựng chuỗi kết nối được gõ mạnh (SqlConnectionStringBuilder, OleDbConnectionStringBuilder, v.v.) xuất phát. Các nhà xây dựng chuỗi kết nối cho phép các nhà phát triển lập trình tạo các chuỗi kết nối chính xác về mặt cú pháp, phân tích và xây dựng lại các chuỗi kết nối hiện có.

Các lớp con quan tâm là:

System.Data.EntityClient.EntityConnectionStringBuilder
System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder

Ví dụ: để "xem ra Nguồn dữ liệu" từ chuỗi kết nối máy chủ SQL, bạn có thể làm:

var builder = new SqlConnectionStringBuilder(connectionString);
var dataSource = builder.DataSource;

6
Lớp cơ sở DbConnectionStringBuildercó các tính năng xử lý chung có thể được sử dụng mà không cần sử dụng các lớp con:if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }
Olivier Jacot-Descombes

41

Có người bán nhà xây dựng chuỗi kết nối cụ thể từ các nhà cung cấp khác nhau như SqlConnectionStringBuilder, MySqlConnectionStringBuilder, SQLiteConnectionStringBuildervv (tiếc là không có giao diện nào từ MS thời gian này). Nếu không, bạn có DbProviderFactory.CreateConnectionStringBuilder sẽ cung cấp cho bạn một cách khác để viết nó theo cách không liên quan đến nhà cung cấp. Bạn sẽ cần chỉ định nhà cung cấp trong tệp cấu hình và có sẵn phiên bản dll phù hợp. Ví dụ:

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

Tôi đã từng viết phân tích thủ công cho bản thân mình mà không gây rắc rối cho tôi. Sẽ rất đơn giản nếu mở rộng điều này để cung cấp thông tin về các tham số khác (hiện tại nó chỉ dành cho những thứ đơn giản như tên db, nguồn dữ liệu, tên người dùng và mật khẩu). Thích cái này hay sao:

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

Đối với điều này, bạn không cần bất cứ điều gì đặc biệt trong tập tin cấu hình, hoặc bất kỳ dll nào cả. Containstrong Wheremệnh đề chỉ quan trọng nếu bạn cần bỏ qua các kết nối được định dạng kém như server = localhost;pp;nơi không ppthêm gì. Để hành xử như những người xây dựng bình thường (sẽ phát nổ trong những trường hợp này) thay đổi Wherethành

.Where(kvp => !string.IsNullOrWhitespace(kvp))

@Icarus không thực sự kể từ khi so sánh chính của từ điển là StringComparer.InvariantCultureIgnoreCase. Xem ToDictionarytình trạng quá tải
nawfal

1
Đúng, bạn nói đúng, tôi vừa viết một bài kiểm tra nhanh. Sẽ xóa nhận xét ban đầu của tôi vì nó sai.
Icarus

3
Phương thức GetValue () của bạn sẽ không hoạt động trong trường hợp ví dụ người dùng có ';'hoặc '='nhập mật khẩu của họ. Tôi đã viết một triển khai tương tự và học được rằng nó không hoạt động một cách khó khăn. Trời ạ, phân tích chuỗi kết nối thực sự khó hơn tôi nghĩ rất nhiều!
Philip Atz

@Joshua Tôi hy vọng bạn đang nói về phần phân tích cú pháp thủ công. Vui lòng lấy câu trả lời ở đây làm điểm khởi đầu có thể được thực hiện thay vì các giải pháp thử nghiệm và chiến đấu. Tôi hy vọng chúng có giá trị hơn những bình luận không để lại thông tin. Bạn cũng được tự do downvote. Theo tôi biết, những gì cần phải được thực hiện thêm là tuân thủ các tiêu chuẩn phân tích cú pháp. MS có một cái trên msd và tôi đã rất lâu mới có thể hiểu được. Giá như tất cả chúng ta đều có thời gian. '@' tất cả xin lưu ý các trường hợp cạnh, đặc biệt là một trong nhận xét của Philip Atz.
nawfal

@nawfal: Tôi đến và để lại câu trả lời khi tôi giải quyết nó.
Joshua

15

Đây là một vài dòng mã sẽ phân tích bất kỳ chuỗi kết nối nào vào từ điển:

Dictionary<string, string> connStringParts = connString.Split(';')
    .Select(t => t.Split(new char[] { '=' }, 2))
    .ToDictionary(t => t[0].Trim(), t => t[1].Trim(), StringComparer.InvariantCultureIgnoreCase);

Và sau đó bạn có thể truy cập bất kỳ phần nào:

string dataSource = connStringParts["Data Source"];

3
Thông minh, điều duy nhất tôi sẽ thay đổi sẽ được bao gồm StringSplitOptions.RemoveEmptyEntriescho lần phân chia đầu tiên vì nó sẽ gây ra IndexOutOfRangengoại lệ nếu có dấu vết;
Scott Chamberlain

2
Điều này hoạt động, nhưng các trình xây dựng chuỗi kết nối mạnh mẽ hơn. Mã như thế này sẽ đưa ra các ngoại lệ cấp thấp thay vì các lỗi phân tích cú pháp có ý nghĩa hơn trong trường hợp chuỗi kết nối không hợp lệ.
Sam

Điều này giúp tôi phân tích chuỗi kết nối ADO để tôi có thể xây dựng một chuỗi tương đương SqlConnectionvới SqlConnectionStringBuilder.
Nhà phát triển toàn diện

Một số hãy cẩn thận ở đây. Ví dụ, giá trị chuỗi kết nối có thể được đặt trong dấu ngoặc kép.
Seva Alekseyev

6

Sử dụng SqlConnectionStringBuilder Thật không may, bạn sẽ phải sử dụng một ConnectionStringBuilder cụ thể của DB vì các chuỗi kết nối khác nhau.



4

Có, bạn có thể làm điều này bằng cách sử dụng các lớp ConnectionStringBuilder. Dưới đây là danh sách các triển khai DbConnectionStringBuilder có sẵn cho các nhà cung cấp dữ liệu tiêu chuẩn:

System.Data.Odbc.OdbcConnectionStringBuilder
System.Data.OleDb.OleDbConnectionStringBuilder
System.Data.OracleClient.OracleConnectionStringBuilder
System.Data.SqlClient.SqlConnectionStringBuilder

đây là ví dụ mẫu về chuỗi kết nối phân tích cú pháp và hiển thị các phần tử của nó.

 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

Bạn có thể sử dụng DbConnectionStringBuilder và bạn không cần bất kỳ nhà cung cấp cụ thể nào:

Các mã sau đây:

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

Đầu ra cho bàn điều khiển:

Data Source: data source value
Server: ServerValue

BIÊN TẬP:

Vì DbConnectionStringBuilder thực hiện IDadata, bạn có thể liệt kê các tham số chuỗi kết nối:

foreach (KeyValuePair<string, object> kv in builder)
{
    Console.WriteLine("{0}: {1}", kv.Key, kv.Value);
}

Điều này giả định rằng bạn đã biết rằng chuỗi kết nối có giá trị "Nguồn dữ liệu", v.v., điều này không phải lúc nào cũng đúng, như đã lưu ý trong stackoverflow.com/a/15529085/534109 , ở trên.
Tieson T.

Câu trả lời của tôi bổ sung cụ thể những gì op yêu cầu: 'Tôi muốn có thể xem ra ví dụ "Nguồn dữ liệu"'
Jesús López

Tôi chỉnh sửa nó để hiển thị tất cả các tham số chuỗi kết nối.
Jesús López

1

Tôi không thực sự thích tất cả các câu trả lời ở đây. Vì vậy, đây là những gì tôi tìm thấy.

Với .NET Core

Bạn có thể sử dụng DbConnectionStringBuildertrực tiếp:

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

0

Vì vậy, tôi thấy tất cả các câu trả lời hiện có ít nhiều sai. Tôi đã kết thúc với giải pháp tầm thường sau đây:

class ConnectionStringParser: DbConnectionStringBuilder {
    ConnectionStringParser(string c) { Connection = c; }
    public override bool ShouldSerialize(string keyword) => true;
}

Trình phân tích cú pháp nằm trong DbConnectionStringBuilder và khá dễ dàng để truy cập. Điều ngớ ngẩn duy nhất chúng ta phải làm là đặt ShouldSerialize luôn luôn trả về giá trị true để tránh mất các thành phần khi cố gắng thực hiện các chuỗi kết nối tùy ý.


2
Điều gì đã sai với câu trả lời hiện có? Hoặc giải pháp của bạn là gì. Giải thích sẽ hữu ích.
nawfal
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.