C #에 연결 문자열 파서가 있습니까?


181

연결 문자열이 있는데 예를 들어 "데이터 소스"를 볼 수 있기를 원합니다. 파서가 있습니까, 아니면 문자열을 검색해야합니까?

답변:


305

예, 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;

6
기본 클래스 DbConnectionStringBuilder에는 서브 클래스를 사용하지 않고 사용할 수있는 일반 처리 기능이 있습니다.if (builder.TryGetValue("Password", out var pwd)) { string decrypted = SomehowDecrypt(pwd); builder["Password"] = decrypted; }
Olivier Jacot-Descombes

41

같은 다양한 업체의 벤더 고유 연결 문자열 빌더가 있습니다 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에 특별한 것이 필요하지 않습니다. Containsin Where절은 server = localhost;pp;where pp에 아무것도 추가하지 않는 것과 같이 형식이 잘못된 연결 문자열을 무시해야하는 경우에만 중요합니다 . 변경 (이 경우에 폭발 할 것이다) 일반 빌더처럼 행동하기 Where에를

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

@Icarus는 사전의 키 비교기가 실제로이기 때문에 실제로는 아닙니다 StringComparer.InvariantCultureIgnoreCase. ToDictionary오버로드 보기
nawfal

1
네, 맞습니다. 방금 빠른 테스트를 작성했습니다. 원래 의견이 잘못되었으므로 삭제합니다.
이카루스

3
예를 들어 사용자가 ';'또는 '='비밀번호를 가지고있는 경우 GetValue () 메소드가 작동하지 않습니다 . 비슷한 구현을 작성했으며 그것이 효과가 없다는 것을 알게되었습니다. 어쨌든 연결 문자열 구문 분석은 실제로 생각보다 훨씬 어렵습니다!
Philip Atz

@Joshua 수동 구문 분석 부분에 대해 이야기하기를 바랍니다. 여기에서 무모하고 전투 테스트 된 솔루션이 아니라 작업을 시작할 수있는 출발점으로 여기에 답하십시오. 나는 그들이 정보를 남기지 않는 의견보다 더 가치가 있기를 바랍니다. 또한 공감할 수 있습니다. 내가 아는 한, 추가로 수행해야 할 것은 구문 분석 표준을 준수하는 것입니다. MS는 msdn에 하나가 있으며 수정해야 할 것이 오래되었습니다. 우리 모두에게 시간이 있었다면. '@'필립 아츠 (Philip Atz)의 의견에서 가장 중요한 사례를 명심하십시오.
nawfal

@ nawfal : 나는 해결하고 나면 대답을 남겼습니다.
Joshua

15

다음은 연결 문자열을 사전으로 구문 분석하는 몇 줄의 코드입니다.

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

3
현명한, 내가 바꿀 유일한 것은 후행이있을 경우 예외 StringSplitOptions.RemoveEmptyEntries를 일으킬 수 있기 때문에 첫 번째 분할에 포함되는 것입니다IndexOutOfRange;
Scott Chamberlain

2
이것은 작동하지만 연결 문자열 작성기가 더 강력합니다. 이와 같은 코드는 잘못된 연결 문자열의 경우 더 의미있는 구문 분석 오류 대신 하위 수준 예외를 발생시킵니다.
Sam

이를 통해 ADO 연결 문자열을 구문 분석하여 SqlConnection와 동등한 항목 을 작성할 수있었습니다 SqlConnectionStringBuilder.
전체론 개발자

여기에 몇 가지 경고가 있습니다. 예를 들어 연결 문자열 값은 따옴표로 묶을 수 있습니다.
Seva Alekseyev



4

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

4

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

위의 stackoverflow.com/a/15529085/534109 에서 언급했듯이 연결 문자열에 "데이터 소스"값 등이 이미 있다는 것을 이미 알고 있다고 가정합니다 .
Tieson T.

내 대답은 특히 op가 묻는 것입니다 : '나는 예를 들어 "데이터 소스"를 엿볼 수 있기를 원합니다 "
Jesús López

모든 연결 문자열 매개 변수를 표시하도록 편집했습니다.
Jesús López

1

나는 여기에있는 모든 대답을 정말로 좋아하지 않았습니다. 여기 내가 찾은 것이 있습니다.

.NET Core로

DbConnectionStringBuilder직접 사용할 수 있습니다 :

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

0

그래서 기존의 모든 대답이 다소 틀렸다는 것을 알았습니다. 나는 다음과 같은 사소한 해결책으로 끝났습니다.

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

파서는 DbConnectionStringBuilder에 있으며 쉽게 얻을 수 있습니다. 우리가 해야하는 유일한 바보는 임의의 연결 문자열을 왕복하려고 할 때 구성 요소가 손실되지 않도록 ShouldSerialize가 항상 true를 반환하도록 설정하는 것입니다.


2
기존 답변에 어떤 문제가 있습니까? 또는 솔루션이 무엇을 수정합니까? 설명이 도움이 될 것입니다.
nawfal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.